Introduction to C# John K. Bennett
with thanks to:
Anders Hejlsberg
Distinguished Engineer Developer Division Microsoft Corporation
Introduction to C# John K. Bennett with thanks to: Anders - - PowerPoint PPT Presentation
Introduction to C# John K. Bennett with thanks to: Anders Hejlsberg Distinguished Engineer Developer Division Microsoft Corporation Key Language Features Unified object system Everything is an object, even primitives Single
Distinguished Engineer Developer Division Microsoft Corporation
Everything is an object, even primitives
Specify methods & interfaces, but no implementation
A restricted, lightweight (efficient) type
Expressive typesafe function pointer
Useful for strategy and observer design patterns
Properties, methods, events Design-time and run-time attributes Integrated documentation using XML
No header files, IDL, etc. Can be embedded in web pages
Traditional views
C++, Java: Primitive types are “magic” and do
not interoperate with objects
Smalltalk, Lisp: Primitive types are objects, but
at great performance cost
C# unifies with no performance cost
Deep simplicity throughout system
Improved extensibility and reusability
New primitive types: Decimal, SQL… Collections, etc., work for all types
No memory leaks and stray pointers
Error handling is not an afterthought
No uninitialized variables, unsafe casts
Pervasive versioning considerations in
/* comment */
// comment
Automatic XML commenting facility
A class combines together
Data
Class variables
Behavior (code for manipulating these data)
Methods
This is a key feature of object-oriented languages
Class and Instances
Class defines a “template”
Instances of a class represent reified, well, instances
Each instance gets its own copy of the class variables;
except “static” methods and variables are unique to the class.
Example: Class Person, where each instance has a unique age, height, name, etc.; the static class variable numPersons keeps track of how many instances of Person we have created.
If class B inherits from base class A, it gains all of the variables and methods of A
Class B can optionally add more variables and methods
Class B can optionally “override” (change) the methods of A
Reuse of class by specializing it for a specific context
Extending a general class for more specific uses
Allow reuse of method definitions of interface
Subclass must implement method definitions
class A { public void display_one() { System.Console.WriteLine("I come from A"); } } class B : A { public void display_two() { System.Console.WriteLine("I come from B, child of A"); } } class App { static void Main() { A a = new A(); // Create instance of A B b = new B(); // Create instance of B a.display_one(); // I come from A b.display_one(); // I come from A b.display_two(); // I come from B, child of A } }
Abstract
indicates an incomplete implementation.
can be used with classes, methods, properties, indexers, and events.
When used with classes, indicates a class intended only to be a base class of other classes.
Members marked as abstract, or included in an abstract class, must be implemented (overridden) by classes that derive from the abstract class.
Virtual
used to modify a method, property, indexer, or event declaration
may be overridden in a derived class.
public abstract class myBase { // If you derive from this class you must implement this method. notice we have no method body here either public abstract void YouMustImplement(); // If you derive from this class you can change the behavior of this method, but are not required to public virtual void YouMayOverride() { } } public class MyBase { // This will not compile because you cannot have an abstract method in a non-abstract class public abstract void YouMustImplement(); }
A class is a container for data and behavior
Often want to control over which code:
1.
Can read & write data
2.
Can call methods
public
No restrictions. Members visible to any method of any class
private
Members in class A marked private only accessible to methods of class A
Default visibility of class variables
protected
Members in class A marked protected accessible to methods
class A { public int num_slugs; protected int num_trees; … } class B : A { private int num_tree_sitters; … } class C { … }
num_slugs: is public
num_trees: is protected, but is defined in A
Class B can see:
num_slugs: is public in A
num_trees: is protected in parent A
num_tree_sitters: is private, but is defined in B
Class C can see:
num_slugs: is public in A
Can’t see:
num_trees: protected in A
num_tree_sitters: private in B
This causes the “constructor” to be called
Creates object but takes no other action
Has same name as the class
Can take arguments
Usually public, though not always
Constructor may be private to ensure that only one
Holds a boolean value, “true” or “false”
Integer values are not equivalent to boolean values
0 does not equal false
There is no built-in conversion from integer to boolean
A fixed precision number up to 28 digits plus decimal point
Example: 300.5m
Suffix “m” or “M” indicates decimal
public enum TokenType { KEYWORD, SYMBOL, IDENTIFIER, INT_CONST, STRING_CONST, UNKNOWN}; public TokenType tokenType = TokenType.UNKNOWN;
C# supports C/C++/Java syntax for “if” statement
Expression must evaluate to a bool value
No integer expressions here
== means “equal to” for boolean comparison
if (i == 5) // if i equals 5
if (i = 5) // error, since i = 5 is not a boolean expression
using System; if (i < 5) { Console.WriteLine(“i is < 5”); } else { Console.WriteLine(“i is >= to 5”); }
Alternative to if-else chains
Typically use break; use goto to continue to another case (fall-thru is illegal, except for empty cases)
const int raining = 1; const int snowing = 0; int weather = snowing; switch (weather) { case snowing: System.Console.Writeln(“It is snowing!”); goto case raining; case raining; System.Console.Writeln(“I am wet!”); break; default: System.Console.Writeln(“Weather OK”); break; }
Namespaces
Contain types and other namespaces
Type declarations
Classes, structs, interfaces, enums,
and delegates
Members
Constants, fields, methods, properties, indexers,
events, operators, constructors, destructors
Organization
No header files, code written “in-line” No declaration order dependence
// Si Simpl mple C# e C# exa exampl mple using ing Sy System; stem; cl class ss He Hello lo { stati atic voi c void M d Main ain() { () { Console nsole.Wr .Write iteLine Line("He "Hello llo worl world") d"); } }
there is no current instance of the class. It’s a class method, not an instance method.
using using Syst System em; us using ing Syst ystem. em.Coll
ectio tions ns; pu publi blic c cla class ss Samp ample lesSt sStack ack { pub public ic sta static ic vo void id Mai Main() () { { // C / Crea reates es an and i d init nitiali alize zes a s a ne new St Stac ack. k. Stac tack k my mySta Stack ck = n = new ew Sta Stack ck(); (); mySt yStack ack.Pus Push("He "Hello llo"); ); mySt yStack ack.Pus Push("Wo "World rld"); ); mySt yStack ack.Pus Push("!" "!"); ); // / Di Disp splay ays s the he p pro roper erti ties s an and d val alue ues o
f th the S Sta tack. k. Cons
Write teLin Line( " ( "myS mySta tack ck" ); " ); Cons
Write teLin Line( " ( "\tCo tCount nt: : {0} {0}", ", myS myStac tack.C k.Cou
nt ); ); Cons
Write te( " ( "\tVa tValue lues:" ) " ); Prin rintVa tValues ues( ( myStack myStack ); ); } pub public ic sta static ic vo void id Pri PrintVa tValu lues es( ( IEn IEnume umera rable ble myC myColl
ectio tion ) ) { { fore
ach ( O ( Obj bject ect obj
in myCo yColle llectio tion ) Con Conso sole. le.Wr Write ite( " ( " {0 {0}", }", obj
); Cons
Write teLin Line(); (); } } /* This code produces: myStack Count: 3 Values: ! World Hello */
using System; // This is a two-pass assembler that mostly follows the book. // The output file name is generated from the input file name, then the two assembler passes are called. namespace csasm { class Program { // Output file extension const string OUT_EXT = "hack"; static void Main(string[] args) // if you want to use command-line args they are available in this array { Console.WriteLine("Enter input filename.asm:"); // Prompt string inFileName = Console.ReadLine(); string outFileName = inFileName; // Get rid of the ".asm" and replace with ".hack"; don't look for "asm, just delete the last 3 chars
// Assemble the file Assembler assem = new Assembler(); assem.pass1(inFileName); assem.pass2(inFileName, outFileName); // Suspend the screen (this is a little feedback to the user that things likely worked). Console.WriteLine("Press return to exit\n"); Console.ReadLine(); } } }
using System; using System.IO; … public void pass1(string inFileName) { … StreamReader file = new StreamReader(inFileName); while ((line = file.ReadLine()) != null) { … } file.Close(); } // Pass 1 public void pass2 (string inFileName, string outFileName) { StreamWriter outFile = new StreamWriter(outFileName); StreamReader file = new StreamReader(inFileName); … while ((line = file.ReadLine()) != null) { … writeBinHex(outFile, n); // write the C instruction …
file.Close(); } //Pass 2
Value types
Directly contain data (e.g., integers) Cannot be null (uninitialized)
Reference types
Contain (pointers) references to objects May be null
int int i = 238; = 238; string s = "Hello world"; string s = "Hello world"; 238 238 i s "Hello world" "Hello world"
Primitives
int i; int i;
Enums
enum Sta enum State { Off te { Off, On } , On }
Structs
struct P struct Point { i
nt x, y; } }
Classes
class Fo class Foo: Bar,
IFoo {...} .}
Interfaces
interfac interface IFoo: e IFoo: IBar {.. IBar {...} .}
Arrays
string[] a = new string[10]; string[] a = new string[10];
Delegates
delegate delegate void Em void Empty(); pty();
Reference
Signed
Unsigned
Character
Floating-point
Logical
For example, int == System.Int32
High C++ fidelity If, while, do require bool condition goto can’t jump into blocks Switch statement
No fall-through, “goto case” or “goto default”
foreach statement Checked and unchecked statements Expression statements must do work
void Foo() { void Foo() { i == 1; // error i == 1; // error }
Constants, fields, methods, properties,
Static and instance members Nested types
public, protected, internal, private
Stored in-line, not heap allocated Assignment copies data, not reference No inheritance
e.g., complex #, point, rectangle, color
No heap allocation (so memory does not
More efficient use of memory
cl clas ass s CPoi CPoint nt { { int int x x, , y; . y; ... .. } } struct S struct SPoint { Point { int x, y int x, y; ... } ; ... } CPoint c CPoint cp = new p = new CPoint(1 CPoint(10, 20); 0, 20); SPoint s SPoint sp = new p = new SPoint(1 SPoint(10, 20); 0, 20);
10 10 20 20 sp sp cp cp 10 10 20 20 Cpoint Cpoint Class Class
Interfaces represent “contracts,” containing only the signatures of components that must be implemented by derived structs and classes.
Interfaces are inherited by structs and classes, which must provide an implementation for each interface member declared.
Interfaces allow us to build “plug-and-play”- like architectures where components can be interchanged at will. Since all interchangeable components implement the same interface, they can be used without additional programming. The interface forces each component to expose specific public members that will be used in a certain way.
In the following example, class ImplementationClass must implement a method named SampleMethod that has no parameters and returns void.
in inter terfa face ce ISa ISample pleIn Inter terfac face { voi void S d Samp ample leMet Method hod(); ); } cla class ss Imp Impleme ement ntati ationC
ass : : IS ISamp ampleIn eInte terfa rface ce { // // Exp Explic licit it in inter terface ace m memb ember er impl mplem ement entati ation: n: voi void I d ISam Sampl pleIn eInter terface ace.S .Samp ampleM leMetho thod( d() { // // Me Meth thod
impleme ement ntati ation.
} sta static tic vo void id Ma Main( in() { // // De Decl clare are an an int inter erfac face i e insta stanc nce. e. ISamp ISampleInt leInter erface face obj =
new Im ew Impleme plement ntation ationClass Class() (); // // Ca Call ll th the m e membe mber. r.
j.Sam ample pleMet Method(
); } }
No implicit conversions to/from int Operators: +, -, ++, --, &, |, ^, ~
byte, short, int, long
enum enum Color: byte Color: byte { Red = 1, Red = 1, Green = 2, Green = 2, Blue = 4, Blue = 4, Black = 0, Black = 0, White = Red | Green | Blue White = Red | Green | Blue }
A delegate is similar to a function pointer in C or C++.
Delegates encapsulate a reference to a method inside a delegate object. The delegate object can then be passed to code that can call the referenced method, without having to know at compile time which method will be invoked. Unlike function pointers in C or C++, delegates are object-oriented, type-safe, and secure.
A delegate declaration defines a type that encapsulates a method with a particular set of arguments and return type.
Delegates form the foundation for events in C#
public delegate void Del(string message); // Create a method for a delegate. public static void DelegateMethod(string message) { System.Console.WriteLine(message); } // Instantiate the delegate. Del handler = DelegateMethod; // Call the delegate. handler("Hello World");
All types ultimately inherit from object Any piece of data can be stored,
Stream MemoryStream FileStream Hashtable double int
Allocates box, copies value into it
Checks type of box, copies value out
int i = 123; int i = 123;
int j = (int)o; int j = (int)o; 123 123 i
123 System.Int32 System.Int32 123 123 j
Natural syntax, accessors, inlining
pu publi blic c cla class ss Butt utton
: Cont
{ pri private ate st string ing c capt aption ion; pub public ic str string ng Ca Capti ption
get et { ret retur urn c n cap aptio tion; n; } set et { cap capti tion
= val value; ue; Rep Repai aint( nt(); ); } } } Butto Button b = n b = n new Bu ew Button( tton(); ); b. b.Cap Capti tion
= "OK"; K"; St Strin ring g s = s = b. b.Capt aptio ion; n;
forea reach ch (Cust (Custome
r c in c in cust ustome
rs.Order derBy( By("name "name")) ")) { { if (c (c.Orde .Orders. rs.Cou Count != nt != 0) 0) { { ... ... } } publi blic s c static tatic vo void id Main( Main(str string ing[] ar [] args) gs) { { forea reach (s ch (stri tring ng s in s in arg args) s) Conso Console. le.Wri WriteLin teLine(s e(s); ); }
cl class ass X XmlE mlElem lement nt { // /// <su / <summ mmary> ary> /// /// Ret Returns rns t the he att attribu ibute te wi with th the he gi given ven na name a e and nd /// /// nam namespa space ce</s </summ ummary> ry> /// /// <pa <param ram nam name= e="na "name" me"> /// /// The The nam name e of
the att attri ribut bute</ e</para aram> m> // /// <pa / <para ram nam m name="ns e="ns"> "> /// /// The The nam names espac pace o e of th the e att attrib ribute, te, o
r null ull if if /// /// the the att attri ribut bute h e has n s no
namesp espace< ce</p /para aram> m> /// /// <re <retur turn> /// /// The The att attri ribut bute v e value lue, , or
null if if t the he att attribu ibute te // /// / do does no es not exi t exist st</ret </return> urn> /// /// <se <seeal ealso c
ref=" f="Get GetAttr ttr(s (stri tring) ng)"/> /> /// /// pub public ic str string ng Ge GetAt tAttr( tr(stri tring ng na name, me, str strin ing n g ns) s) { ... .. } }
Can be overloaded
pu publi blic c cla class ss List istBo Box: x: Con Control rol { pri private ate st string ing[] [] it items ems; pub public ic str string ng th this[ is[int int ind index ex] { ] { get et { ret retur urn i n ite tems[ ms[ind index]; x]; } set et { ite items ms[in [inde dex] x] = v = value lue; Rep Repai aint( nt(); ); } } } ListB ListBox li
stBox = Box = new new Li ListBox stBox(); (); li listB stBox
[0] = = "hel hello lo"; "; Co Conso nsole le.Wr .Write iteLine ine(l (list istBox Box[0]) 0]);
Decimal, DateTime, TimeSpan
Unit, Point, Rectangle
SQLString, SQLInt16, SQLInt32,
pu publi blic c str struct uct DBI DBInt nt { pu public blic st static atic reado readonl nly DBI y DBInt Nu nt Null ll = ne = new DBI w DBInt nt(); (); pri private ate in int va valu lue; e; pri private ate bo bool d l def efine ined; d; pu public blic bo bool Is
Null { { get { get { retu return rn !def !defined; ined; } } } } pub public ic sta static ic DB DBInt Int op
rator
+(DBI DBInt x t x, , DBI DBInt nt y) { ) {.. ...} .} pub public ic sta static ic im impli plicit cit ope
rator tor DB DBInt( nt(in int x t x) { ) {...} ..} pu public blic st static atic expli explici cit ope t operator rator i int(DB nt(DBInt x Int x) ) {...} {...} } DB DBInt Int x x = = 123 123; DB DBInt Int y y = = DBI DBInt.N t.Nul ull; l; DB DBInt Int z z = = x + x + y; y;
Simple boolean logic
pu publi lic c class ass Deb ebug { [Cond
itional( al("De "Debug") bug")] publi blic sta c static tic vo void As id Asser sert(b t(bool c
, String tring s) s) { { if (!co (!cond) nd) { { thro hrow n w new ew Asser Assertio tionEx nExcepti ception(
s); } } }
Platform interoperability covers most cases Unsafe code
Low-level code “within the box” Enables unsafe casts, pointer arithmetic
Declarative pinning
Fixed statement
Basically “inline C”
unsaf safe v e void F
) { ch char* r* buf buf = s stac ackallo alloc c char ar[256] 256]; for ( r (char* char* p p = b = buf; p uf; p < < buf buf + 25 + 256; 6; p++ p++) *p ) *p = 0 = 0; ... ... }
cl class ass F File ileStr Stream: am: S Stre tream am { in int han t handl dle; e; pub public ic uns unsafe fe in int R t Read ead(byt byte[ e[] b ] buff uffer, r, in int i t inde ndex, i , int nt co count unt) { { int nt n = n = 0; 0; fixe ixed ( d (byte yte* * p = p = bu buffer fer) ) { Re Read adFil ile( e(han andl dle, e, p p + + ind ndex ex, , cou
nt, & &n, n, n null ll); ); } retu eturn rn n; } [d [dllimp llimpor
t("kernel3 rnel32" 2", Set , SetLastE LastErr rror=tr
ue)] sta static ic ext extern rn un unsaf safe b e bool
ReadF adFile ile(int int h hFil File, e, void
* lpBuf Buffe fer, r, int int nBy nByte tesTo sToRea Read, int* nt* nB nBytes tesRe Read, ad, Ov Overla rlapp pped* ed* lp lpOver verla lappe pped); d); }
(Allow Unsafe Code must be set for the project)
// Normal pointer to an object. int [] a = new int[5] {10, 20, 30, 40, 50}; // Must be in unsafe code to use interior pointers. unsafe { // Must pin object on heap so that it doesn't move. fixed (int* p = &a[0]) { // p is pinned as well as object, so create another pointer int* p2 = p; Console.WriteLine(*p2); // Incrementing p2 bumps the pointer by four bytes p2 += 1; Console.WriteLine(*p2); p2 += 1; Console.WriteLine(*p2); Console.WriteLine("--------"); Console.WriteLine(*p); // Deferencing p and inc’ing changes the value of a[0] ... *p += 1; Console.WriteLine(*p); *p += 1; Console.WriteLine(*p); } } Console.WriteLine("--------"); Console.WriteLine(a[0]); Console.ReadLine(); // Output: //10 //20 //30 //-------- //10 //11 //12 //-------- //12
Problem in most languages
C++ and Java produce fragile base classes Users unable to express versioning intent
C# allows intent to be expressed
Methods are not virtual by default C# keywords “virtual”, “override” and “new”
provide context
C# can't guarantee versioning
Can enable (e.g., explicit override) Can encourage (e.g., smart defaults)
class ass De Derived rived: B : Base ase // ve versi rsion 1
{ publi blic vir c virtua tual v l void F
) { Console nsole.Wr .Write iteLine( Line("De "Deriv rived.Fo ed.Foo")
; } } class ass De Derived rived: B : Base ase // ve versi rsion 2a
{ new p w public ublic vi virtu rtual vo al void id Foo Foo() { () { Console nsole.Wr .Write iteLine( Line("De "Deriv rived.Fo ed.Foo")
; } } class ass De Derived rived: B : Base ase // ve versi rsion 2b
{ publi blic ove c overri rride de void void Foo Foo() () { base.Fo se.Foo()
Console nsole.Wr .Write iteLine( Line("De "Deriv rived.Fo ed.Foo")
; } } class ass Ba Base se // ve versi rsion 1
{ } class ass Ba Base se // ve versi rsion 2
{ publi blic vir c virtua tual v l void F
) { Console nsole.Wr .Write iteLine( Line("Ba "Base. se.Foo") Foo"); ; } }
pu publi blic c del delega egate v e voi
d Even ventHan Handl dler( er(obj
ct se sende nder, r, Even ventA tArgs rgs e) e); pu publi blic c cla class ss Butt utton
{ pub public ic eve event E t Eve ventH ntHand andler er Cl Click ick; pro protect ected ed void
OnCl nClick ick(Eve Event ntArg Args e s e) { { if ( f (Cli Click ! k != = nul null) l) Clic lick( k(thi this, s, e); ); } }
publi public cla c class ss MyFo MyForm: F rm: For
{ But Button
tton; n; pub public ic MyF MyForm( rm() ) {
kBut utto ton = = n new w Bu Butt tton( n(.. ...); );
kButto tton.Ca .Capt ption ion = = "OK" OK";
kButto tton.Cl .Clic ick + k += n = new E w Eve ventH ntHand andler( er(Ok OkBut Button tonClic lick) k); } vo void Ok id OkBu ButtonC ttonClick( lick(ob
ject sende sender, r, Even EventArgs tArgs e e) { ) { Show howMes Message age(" ("You You pr presse ssed d the the OK OK but butto ton") n"); } }
Documentation URL for a class Transaction context for a method XML persistence mapping
Add keywords or pragmas to language Use external files, e.g., .IDL, .DEF
Attributes can be
Attached to types and members Examined at run-time using reflection
Completely extensible
Simply a class that inherits from
System.Attribute
Type-safe
Arguments checked at compile-time
Extensive use in .NET Framework
XML, Web Services, security, serialization,
pu publi blic c cla class ss Orde rderP rProc rocess essor { [W [WebMet ebMetho hod] d] pub public ic voi void Su Subm bmitO itOrde rder(Pu (Purc rchas haseOr eOrder er or
der) { ) {...} ..} } [X [XmlR mlRoo
t("Ord Order", r", N Name amespa space=" e="ur urn:a n:acme cme.b2b b2b-sche chema. ma.v1") 1")] publi public cla c class ss Purc PurchaseO haseOrd rder er { [Xm [XmlEle Elemen ment("s ("shi hipTo pTo")] ")] pu publ blic ic Add Address ess S Ship hipTo; To; [Xm [XmlEle Elemen ment("b ("bil illTo lTo")] ")] pu publ blic ic Add Address ess B Bill illTo; To; [Xm [XmlEle Elemen ment("c ("com
ment") t")] pu publ blic ic str string ng Co Comme mment; nt; [X [XmlEle mlEleme ment("i nt("items" tems")] )] pu public blic It Item[] em[] Items Items; [Xm [XmlAtt Attrib ribute( te("d "date ate")] ")] pu publ blic ic Dat DateTim Time e Ord OrderD erDate; te; } pu publi blic c cla class ss Addr ddres ess { s {... ...} pu publi blic c cla class ss Item tem { {... ...}
Eliminates “wrapper classes” Collection classes work with all types Replaces OLE Automation's Variant
string s = string.Format( string s = string.Format( "Your total was {0} on {1}", total, date); "Your total was {0} on {1}", total, date); Hashtable t = new Hashtable(); Hashtable t = new Hashtable(); t.Add(0, "zero"); t.Add(0, "zero"); t.Add(1, "one"); t.Add(1, "one"); t.Add(2, "two"); t.Add(2, "two");
Properties, methods, events Integrated help and documentation Design-time information
Not naming patterns, adapters, etc. Not external files
Type-safe, unlike C++
vo void d pri rintf(s tf(stri ring g fmt, mt, par arams ms obje
t[] a args) gs) { forea reach (o ch (obje bject ct x in x in arg args) s) { ... ... } } print intf(" f("%s %i %s %i %i %i", ", str, str, int int1, 1, int2) int2);
ject[] t[] args args = = new new obje
ct[3]; 3]; args[ gs[0] 0] = str = str; args[ gs[1] 1] = int = int1; 1; Args[ gs[2] 2] = int = int2; 2; print intf(" f("%s %i %s %i %i %i", ", args) args);