Introduction to CIntroduction to C##
Based on slides fromBased on slides from
Stephen TurnerStephen TurnerLuca BologneseLuca BologneseAnders HejlsbergAnders HejlsbergPeter SestoftPeter Sestoft
Language ComparisonsLanguage Comparisons60% Java, 10% C++, 10% VB, 20% 60% Java, 10% C++, 10% VB, 20% newnew
As in JavaAs in Java Object-orientation Object-orientation
(single inheritance)(single inheritance) NamespacesNamespaces
(like packages)(like packages) InterfacesInterfaces Strong typingStrong typing ExceptionsExceptions ThreadsThreads Garbage collectionGarbage collection ReflectionReflection Dynamic loadingDynamic loading
of codeof code
As in C++As in C++ Operator overloadingOperator overloading Pointer arithmetic in Pointer arithmetic in
unsafe codeunsafe code Some syntactic Some syntactic
detailsdetailsAs in VBAs in VB PropertiesProperties EventsEvents RAD developmentRAD development
Language ComparisonsLanguage ComparisonsAdvancements on JavaAdvancements on Java
Really newReally new Objects on the stack Objects on the stack
(structs)(structs) Boxing / unboxingBoxing / unboxing DelegatesDelegates AttributesAttributes Ref and out Ref and out
parametersparameters Rectangular arraysRectangular arrays EnumerationsEnumerations Unified type systemUnified type system gotogoto VersioningVersioning
ProductivityProductivity Component-based Component-based
programmingprogramming PropertiesProperties EventsEvents IndexersIndexers
Operator overloadingOperator overloading foreach statementsforeach statements
Hello, WorldHello, Worldclass Hello{
static void Main() {
System.Console.WriteLine("Hello, World");}
}
Hello, WorldHello, Worldusing System;
class Hello{
static void Main() {
Console.WriteLine("Hello, World");}
}
Hello, WorldHello, Worldusing System;
namespace Test {class Hello {
static void Main(string[] args) {if (args.Length > 0) {
Person p = new Person(args[0]);Console.WriteLine("Hello, " + p.name);
}}
}
class Person {public string name;public Person(string name) {
this.name = name;}
}}
C# Program StructureC# Program StructureNamespacesNamespaces Contain types and other namespacesContain types and other namespaces
Type declarationsType declarations class, struct, interface, enum and delegateclass, struct, interface, enum and delegate
MembersMembers constant, field, method, property, indexer, constant, field, method, property, indexer,
event, operator, constructor, destructor event, operator, constructor, destructor (finalizer)(finalizer)
OrganizationOrganization No header files, code written “in-line”No header files, code written “in-line” No declaration order dependenceNo declaration order dependence
Unified Type SystemUnified Type SystemTraditional viewsTraditional views C++, Java – primitive types are “magic” C++, Java – primitive types are “magic”
and do not interoperate with objectsand do not interoperate with objects Smalltalk, Lisp – primitive types are Smalltalk, Lisp – primitive types are
objects, but at great performance costobjects, but at great performance costC# unifies with little or no performance C# unifies with little or no performance costcost Deep simplicity throughout systemDeep simplicity throughout system
Improved extensibility and reusabilityImproved extensibility and reusability New primitive types: Decimal, SQL, …New primitive types: Decimal, SQL, … Collections, etc., work for all typesCollections, etc., work for all types
Unified Type SystemUnified Type SystemAll types ultimately inherit from objectAll types ultimately inherit from objectAny piece of data can be stored, Any piece of data can be stored, transported, and manipulated with no transported, and manipulated with no extra workextra work
StreamStream
MemoryStreamMemoryStream FileStreamFileStream
HashtableHashtable doubledoubleintint
objectobject
Value types and reference types (C# Precisely section 5.1, examples 84 and 86)
A C# type is either a reference type (class, interface, array type) or a value type (int, double, . . . ).
A value (object) of reference type is always stored in the managed (garbage-collected) heap.
Assignment to a variable of reference type copies only the reference.
A value of value type is stored in a local variable or parameter, or inline in an array or object or struct value.
Assignment to a variable of value type copies the entire value.Just as in Java. But in C#, there are also user defined value types, called struct types (as in C/C++):
Unified Type SystemUnified Type System
Value & Reference TypesValue & Reference TypesValue typesValue types Variables directly contain dataVariables directly contain data Cannot be nullCannot be null
Reference typesReference types Variables contain references to objectsVariables contain references to objects May be nullMay be null
int i = 123;string s = "Hello world";
123123ii
ss "Hello world""Hello world"
The machine model (C# Precisely example 64)
Class instances (objects) are individuals in the heap.Struct instances are in the stack, or inline in other structs, objects or arrays.
Value & Reference TypesValue & Reference TypesValue typesValue types PrimitivesPrimitives int i; float f;int i; float f; EnumsEnums enum State { Off, On }enum State { Off, On } StructsStructs struct Point { int x, y; }struct Point { int x, y; }
Reference typesReference types ClassesClasses class Foo: Bar, IFoo { … }class Foo: Bar, IFoo { … } InterfacesInterfaces interface IFoo: IBar { … }interface IFoo: IBar { … } ArraysArrays string[] s = new string[] s = new
string[10];string[10]; DelegatesDelegates delegate void Empty();delegate void Empty();
Unified Type SystemUnified Type SystemBoxingBoxing Allocates a box, copies value into itAllocates a box, copies value into it
UnboxingUnboxing Checks type of box, copies value outChecks type of box, copies value out
int i = 123;object o = i;int j = (int) o;
123123i
o
123123System.Int32System.Int32
123123j
Unified Type SystemUnified Type SystemBenefitsBenefits Eliminates the need for wrapper classesEliminates the need for wrapper classes Collection classes work with all typesCollection classes work with all types Replaces OLE Automation's VariantReplaces OLE Automation's Variant Simple, consistent programming modelSimple, consistent programming model
string s1 = String.Format("Your balance is {0} on {1}", 24.95, DateTime.Today);
ArrayList al = new ArrayList();al.Add(new Object());al.Add(1);al.Add("Hello");
string s2 = 24.95.ToString(); // no boxing occurs here
Predefined TypesPredefined TypesC# predefined typesC# predefined types ReferenceReference object, stringobject, string SignedSigned sbyte, short, int, longsbyte, short, int, long UnsignedUnsigned byte, ushort, uint, byte, ushort, uint,
ulongulong CharacterCharacter charchar Floating-pointFloating-point float, double, decimalfloat, double, decimal LogicalLogical boolbool
Predefined types are simply aliases for Predefined types are simply aliases for system-provided typessystem-provided types For example, int = System.Int32For example, int = System.Int32
ClassesClassesInheritanceInheritance Single base classSingle base class Multiple interface implementationMultiple interface implementation
Class membersClass members Constants, fields, methods, properties, Constants, fields, methods, properties,
indexers, events, operators, constructors, indexers, events, operators, constructors, destructorsdestructors
Static and instance membersStatic and instance members Nested typesNested types
Member accessMember access Public, protected, internal, privatePublic, protected, internal, private
InterfacesInterfacesAn interface is a reference type with no An interface is a reference type with no implementation implementation Specify methods, properties, indexers Specify methods, properties, indexers & events& events
interface IDataBound {void Bind(IDataBinder binder);
}
class EditBox : Control, IDataBound {void IDataBound.Bind(IDataBinder binder) {
...}
}
StructsStructsLike classes, exceptLike classes, except Stored on stack or in-line, not heap allocatedStored on stack or in-line, not heap allocated Assignment copies data, not referenceAssignment copies data, not reference Derive from System.ValueTypeDerive from System.ValueType Can not inherit or be inheritedCan not inherit or be inherited Can implement multiple interfacesCan implement multiple interfaces
Ideal for light weight objectsIdeal for light weight objects Complex, point, rectangle, colorComplex, point, rectangle, color int, float, double, etc., are all structsint, float, double, etc., are all structs
BenefitsBenefits No heap allocation, so fast!No heap allocation, so fast! More efficient use of memoryMore efficient use of memory
Classes and StructsClasses and Structs
1010
2020spsp
cpcp
1010
2020
CPointCPoint
Class CPoint { int x, y; ... }struct SPoint { int x, y; ... }
CPoint cp = new CPoint(10, 20);SPoint sp = new SPoint(10, 20);
Rectangular multi-dimensional arrays (C# Precisely section 9.2.1)
In Java, a ‘multi-dimensional’ array is a one-dimensional array of arrays.C# in addition has C-style rectangular multi-dimensional arrays.This improves memory locality (speed) and reduces memory consumption (space).
11stst Class Component Class Component SupportSupport
C# is the first “component oriented” C# is the first “component oriented” language in the C/C++ familylanguage in the C/C++ familyWhat defines a component?What defines a component? Properties & eventsProperties & events Design-time & runtime informationDesign-time & runtime information Integrated help & documentationIntegrated help & documentation
C# has first class supportC# has first class support Not naming patterns, adapters, etc.Not naming patterns, adapters, etc. Not external header or IDL filesNot external header or IDL files
Easy to build & consumeEasy to build & consume
public class Person{
private int age;
public int Age {get {
return age;}set {
age = value;Party();
}}
}
// UnnaturalPerson p = new Person();p.set_Age(27);p.set_Age(p.get_Age() + 1);
// NaturalPerson p = new Person();p.Age = 27;p.Age ++;
PropertiesPropertiesProperties are “smart fields”Properties are “smart fields” Natural syntax, accessors, inliningNatural syntax, accessors, inlining
IndexersIndexersIndexers are “smart arrays”Indexers are “smart arrays” Overloadable for different index Overloadable for different index
signaturessignaturespublic class ListBox : Control{
private string[] items;
public string this[int index] {get {
return items[index];}set {
items[index] = value;Repaint();
}}
}
ListBox lb = new ListBox();
lb[0] = "hello";Console.WriteLine(lb[0]);
DelegatesDelegatesObject oriented function pointersObject oriented function pointers Actually a method typeActually a method type
Multiple receiversMultiple receivers Each delegate has an invocation list (+= Each delegate has an invocation list (+=
& -= ops)& -= ops)delegate double Func(double x);
static void Main() {Func f = new Func(MySin);double x = f(1.0);
}
private static double MySin(double x) {return Math.Sin(x);
}
EventsEventsA “protected delegate”A “protected delegate” Owning class gets full accessOwning class gets full access Consumers can only hook or unhook Consumers can only hook or unhook
handlershandlers Similar to a property – supported with Similar to a property – supported with
metadatametadataUsed throughout the frameworks Used throughout the frameworks Very easy to extendVery easy to extend
Event SourcingEvent SourcingDefine the event signatureDefine the event signature
Define the event and firing logicDefine the event and firing logic
public delegate void EventHandler(object sender, EventArgs e);
public class Button : Control{
public event EventHandler Click;
protected void OnClick(EventArgs e) {if (Click != null) {
Click(this, e);}
}}
Event HandlingEvent HandlingDefine and register event handlerDefine and register event handler
public class MyForm : Form{
Button okButton;
public MyForm() {okButton = new Button();okButton.Text = "OK";okButton.Click += new EventHandler(OkButtonClick);
}
private void OkButtonClick(object sender, EventArgs e) {MessageBox.Show("You pressed the OK button");
}}
MetadataMetadataAssociate with types and membersAssociate with types and members Design time informationDesign time information Transaction context for a methodTransaction context for a method XML persistence mappingXML persistence mapping
Traditional solutionsTraditional solutions Add keywords or pragmas to languageAdd keywords or pragmas to language Use external files, e.g., .IDL, .DEFUse external files, e.g., .IDL, .DEF
Extend the language semanticsExtend the language semantics Expose methods to web servicesExpose methods to web services Set transaction context for a methodSet transaction context for a method
AttributesAttributesAttributes can beAttributes can be Attached to any type and its membersAttached to any type and its members Examined at run-time using reflectionExamined at run-time using reflection
Completely extensibleCompletely extensible Simply a class that inherits from Simply a class that inherits from
System.AttributeSystem.AttributeType-safeType-safe Arguments checked at compile-timeArguments checked at compile-time
Extensive use in .NET frameworkExtensive use in .NET framework Web Services, code security, serialization, Web Services, code security, serialization,
XML persistence, component / control model, XML persistence, component / control model, COM and P/Invoke interop, code COM and P/Invoke interop, code configuration…configuration…
AttributesAttributesAppear in square bracketsAppear in square bracketsAttached to code elementsAttached to code elements Types, members & parametersTypes, members & parameters
[WebService(Namespace="http://microsoft.com/demos/")]class SomeClass{
[WebMethod]void GetCustomers() {}
string Test([SomeAttr] string param1) {}
}
Creating AttributesCreating AttributesAttributes are simply classesAttributes are simply classes Derived from System.AttributeDerived from System.Attribute Class functionality = attribute Class functionality = attribute
functionalityfunctionalitypublic class HelpURLAttribute : System.Attribute{
public HelpURLAttribute(string url) { … }
public string URL { get { … } }public string Tag { get { … } set { … } }
}
Using AttributesUsing AttributesJust attach it to a classJust attach it to a class
Use named parametersUse named parameters
Use multiple attributesUse multiple attributes
[HelpURL(“http://someurl/”)]Class MyClass { … }
[HelpURL(“http://someurl/”, Tag=“ctor”)]Class MyClass { … }
[HelpURL(“http://someurl/”), HelpURL(“http://someurl/”, Tag=“ctor”)]Class MyClass { … }
Querying AttributesQuerying AttributesUse reflection to query attributesUse reflection to query attributes
Type type = typeof(MyClass); // or myObj.GetType()
foreach (Attribute attr in type.GetCustomAttributes()){
if (attr is HelpURLAttribute){
HelpURLAttribute ha = (HelpURLAttribute) attr;myBrowser.Navigate(ha.URL);
}}
Some standard .Net attribute classes
Productivity FeaturesProductivity FeaturesEnumsEnumsforeach statementforeach statementParameter arraysParameter arraysRef and out Ref and out parametersparametersOverflow checkingOverflow checkingUsing statementUsing statement
Switch on stringSwitch on stringOperator overloadingOperator overloadingXML commentsXML commentsConditional Conditional compilationcompilationUnsafe codeUnsafe codePlatform InvokePlatform InvokeCOM interopCOM interop
EnumsEnumsStrongly typedStrongly typed No implicit conversions to/from intNo implicit conversions to/from int Operators: +, -, ++, --, &, |, ^, ~Operators: +, -, ++, --, &, |, ^, ~
Can specify underlying typeCan specify underlying type Byte, short, int, longByte, short, int, long
Supported my metadata & reflectionSupported my metadata & reflectionenum Color: byte {
Red = 1,Green = 2,Blue = 4,Black = 0,White = Red | Green | Blue,
}
foreach Statementforeach StatementIteration of arraysIteration of arrays
Iteration of user-defined collectionsIteration of user-defined collections Or any type that supports IEnumerableOr any type that supports IEnumerable
foreach (Customer c in customers.OrderBy("name")) {
if (c.Orders.Count != 0) {...
}}
public static void Main(string[] args) {foreach (string s in args) {
Console.WriteLine(s);}
}
static void Main() {printf("%s %i %o", "Hello", 29, new Object());
object[] args = new object[3];args[0] = "Hello";args[1] = 29;args[2] = new Object();printf("%s %i %o", args);
}
static void printf(string fmt, params object[] args) {foreach (object x in args) {}
}
Parameter ArraysParameter ArraysCan write “printf” style methodsCan write “printf” style methods Type-safe, unlike C++Type-safe, unlike C++
ref and out Parametersref and out ParametersUse “ref” for in/out parameter passingUse “ref” for in/out parameter passingUse “out” to return multiple valuesUse “out” to return multiple valuesMust repeat ref/out at call siteMust repeat ref/out at call site
static void Swap(ref int a, ref int b) {...}
static void Divide(int dividend, int divisor,out int result, out int remainder) {...}
static void Main() {int x = 1, y = 2;Swap(ref x, ref y);int r0, r1;Divide(3, 2, out r0, out r1);
}
Overflow CheckingOverflow CheckingInteger arithmetic operationsInteger arithmetic operations C, C++, Java silently overflowC, C++, Java silently overflow
checked vs. unchecked contextschecked vs. unchecked contexts Default is unchecked, except for Default is unchecked, except for
constantsconstants Change with “/checked” compiler switchChange with “/checked” compiler switch
int m0 = checked(x * y); // check operator
checked { // check statementint m1 = x * y;
}
using Statementusing StatementAcquire, Execute, Release patternAcquire, Execute, Release patternWorks with any IDisposable objectWorks with any IDisposable object Data access classes, streams, text Data access classes, streams, text
readers and writers, network classes, etc.readers and writers, network classes, etc.Resource res = new Resource(...);try {
res.DoWork();}finally {
if (res != null) {((IDisposable)res).Dispose();
}} using (Resource res = new Resource()) {
res.DoWork();}
Switch on StringSwitch on StringColor ColorFromFruit(string s){
switch(s.ToLower()){
case "apple":return Color.Red;
case "banana":return Color.Yellow;
case "carrot":return Color.Orange;
default:throw new InvalidArgumentException();
}}
Operator OverloadingOperator OverloadingFirst class user-defined data typesFirst class user-defined data typesUsed in base class libraryUsed in base class library Decimal, DateTime, TimeSpanDecimal, DateTime, TimeSpan
Used in the Windows Forms libraryUsed in the Windows Forms library Point, Size, RectanglePoint, Size, Rectangle
Used in the SQL librariesUsed in the SQL libraries SQLString, SQLInt16, SQLInt32, SQLString, SQLInt16, SQLInt32,
SQLInt64, SQLBool, SQLMoney, SQLInt64, SQLBool, SQLMoney, SQLNumeric, SQLFloat…SQLNumeric, SQLFloat…
Operator OverloadingOperator Overloadingpublic struct DBInt{
public static readonly DBInt Null = new DBInt();
private int value;private bool defined;
public bool IsNull { get { return !defined; } }
public static DBInt operator +(DBInt x, DBInt y) {...}
public static implicit operator DBInt(int x) {...}public static explicit operator int(DBInt x) {...}
}
DBInt x = 123;DBInt y = DBInt.Null;DBInt z = x + y;
User-defined conversions (C# Precisely section 10.16)
A user-defined conversion is an operator named by the conversion’s target type.Conversions may be implicit (require no cast) or explicit (require a type cast).Converting between integers, doubles and fractions is useful:
struct Frac : IComparable {public readonly long n, d;public Frac(long n, long d) { ... }public static implicit operator Frac(int n) { return new Frac(n, 1); }public static implicit operator Frac(long n) { return new Frac(n, 1); }public static explicit operator long(Frac r) { return r.n/r.d; }public static explicit operator float(Frac r) { return ((float)r.n)/r.d; }...
}
XML CommentsXML Comments/// denotes an XML comment/// denotes an XML commentCompiler processing:Compiler processing: Verifies well-formed XMLVerifies well-formed XML Verifies parameter namesVerifies parameter names Generates globally unique names, so links Generates globally unique names, so links
can be resolvedcan be resolvedAny XML is okay, can use “standard” Any XML is okay, can use “standard” tags if you want totags if you want toEnables post-processing to final formEnables post-processing to final form
XML CommentsXML Commentsclass XmlElement{
/// <summary>/// Returns the attribute with the given name/// </summary>/// <param name="name">/// The name of the attribute/// </param>/// <return>/// The attribute value, or null/// </return>/// <seealso cref="GetAttr(string)"/>
public string GetAttribute(string name) {...
}}
Extending the Type SystemExtending the Type SystemMost users think of two types of objectsMost users think of two types of objects ““Real” objects – Customer, Order, etc.Real” objects – Customer, Order, etc. Primitive types – int, float, boolPrimitive types – int, float, bool
Different expectations for eachDifferent expectations for each Real objects are more expensive to createReal objects are more expensive to create Primitives always have a valuePrimitives always have a value Primitives have operator supportPrimitives have operator support
Classes and Structs – Classes and Structs – bbest of both est of both worlds!worlds!Natural semantics Natural semantics Operator overloadingOperator overloading & & User conversionsUser conversions
Interface supportInterface support
Rational Numbers (½, ¾, Rational Numbers (½, ¾, 1½)1½)Rational r1 = new Rational(1,2);Rational r2 = new Rational(2,1);
Rational r3 = r1.AddRational(r2);
double d = Rational.ConvertToDouble(r3);
Rational r1 = new Rational(1,2);Rational r2 = 2;
Rational r3 = r1 + r2;
double d = (double) r3;
Rational Number – Class?Rational Number – Class?Heap allocatedHeap allocatedCan be null Can be null ““=” assigns reference not value=” assigns reference not valueArrays allocate references not valuesArrays allocate references not values
public class Rational {
public Rational(int n, int d) { … } }
…
Rational[] array = new Rational[100];
Structs Provide an AnswerStructs Provide an AnswerBehavior differences versus ClassesBehavior differences versus Classes Stored in-line, not heap allocatedStored in-line, not heap allocated Never nullNever null Assignment copies data, not referenceAssignment copies data, not reference
Implementation differencesImplementation differences Always inherit from objectAlways inherit from object Always has a default constructorAlways has a default constructor
Rational Number – StructRational Number – Structpublic struct Rational{
public Rational(int n, int d) { … }
public int Numerator { get{…} }public int Denominator { get{…} }
public override string ToString() { … }}
Rational r = new Rational(1,2);
string s = r.ToString();
Implicit ConversionsImplicit ConversionsNo loss of dataNo loss of data
public struct Rational{
…public static implicit operator Rational(int i){
return new Rational(i,1);}
}
Rational r = 2;
Explicit ConversionsExplicit ConversionsPossible loss of precision and can throw Possible loss of precision and can throw exceptionsexceptions
public struct Rational{
…public static explicit operator double(Rational r){
return (double) r.Numerator / r.Denominator;}
}
Rational r = new Rational(2,3);double d = (double) r;
Operator Overloading Operator Overloading Static operatorsStatic operatorsMust take its type as a parameterMust take its type as a parameter
public struct Rational{
…public static Rational operator+ (
Rational lhs, Rational rhs) {
return new Rational( … );}
}Rational r3 = r1 + r2;
r3 += 2;
Equality OperatorsEquality Operators.NET Framework equality support .NET Framework equality support
.Equals() should use operator==().Equals() should use operator==()
public override bool Equals(object o)
public static bool operator== (Rational lhs, Rational rhs) public static bool operator!= (Rational lhs, Rational rhs)
if ( r1.Equals(r2) ) { … }if ( !r1.Equals(r2)) { … }
if ( r1 == r2 ) { … } if ( r1 != r2 ) { … }
Structs and InterfacesStructs and InterfacesStructs can implement interfaces to Structs can implement interfaces to provide additional functionality provide additional functionality Why? The same reasons classes can!Why? The same reasons classes can!ExamplesExamples System.IComparableSystem.IComparable
Search and sort support in collectionsSearch and sort support in collections System.IFormattableSystem.IFormattable
Placeholder formattingPlaceholder formatting
System.IFormattableSystem.IFormattableTypes can support new formatting Types can support new formatting options through IFormattable options through IFormattable
Rational r1 = new Rational(2,4);
Console.WriteLine(“Rational {0}", r1); Console.WriteLine(“Rational {0:reduced}", r1);
Implementing IFormattableImplementing IFormattablepublic struct Rational : IFormattable {
public string Format(string formatStr, IServiceObjectProvider isop) { s = this.ToString(); if ( formatStr == “reduced" ) { s = … } return s;
}}
Rational r1 = new Rational(2,4); Console.WriteLine("No Format = {0}", r1);Console.WriteLine("Reduced Format = {0:reduced}", r1);
No Format = 2/4Reduced Format = 1/2
Robust and Durable Robust and Durable SoftwareSoftware
Garbage collectionGarbage collection No memory leaks and stray pointersNo memory leaks and stray pointers
ExceptionsExceptions Error handling is not an afterthoughtError handling is not an afterthought
Type-safetyType-safety No uninitialized variables, unsafe castsNo uninitialized variables, unsafe casts
VersioningVersioning Pervasive versioning considerations in all Pervasive versioning considerations in all
aspects of language designaspects of language design
Language Safety vs. C++Language Safety vs. C++If, while, do require bool conditionIf, while, do require bool conditionGoto can’t jump into blocksGoto can’t jump into blocksSwitch statementSwitch statement No fall-throughNo fall-through Break, goto <case> or goto defaultBreak, goto <case> or goto default
Checked and unchecked statementsChecked and unchecked statementsExpression statements must do workExpression statements must do work
void Foo() {i == 1; // error
}
VersioningVersioningOverlooked in most languagesOverlooked in most languages C++ and Java produce fragile base C++ and Java produce fragile base
classes classes Users unable to express versioning intentUsers unable to express versioning intent
C# allows intent to be expressedC# allows intent to be expressed Methods are not virtual by defaultMethods are not virtual by default C# keywords “virtual”, “override” and C# keywords “virtual”, “override” and
“new” provide context“new” provide contextBut C# can't guarantee versioningBut C# can't guarantee versioning Can enable (e.g., explicit override)Can enable (e.g., explicit override) Can encourage (e.g., smart defaults)Can encourage (e.g., smart defaults)
Method Versioning in JavaMethod Versioning in Java
class Derived extends Base // v1.0class Derived extends Base // v1.0{{ public void Foo() public void Foo() {{ System.out.println("Derived.Foo"); System.out.println("Derived.Foo"); }}}}
class Base // v1.0class Base // v1.0{{}}
class Base class Base // v2.0 // v2.0 {{ public void Foo() public void Foo() {{ Database.Log("Base.Foo"); Database.Log("Base.Foo"); }}}}
class Base class Base // v2.0 // v2.0 {{ public public intint Foo() Foo() {{ Database.Log("Base.Foo"); Database.Log("Base.Foo"); }}}}
Method Versioning in C#Method Versioning in C#
class Derived : Base // v1.0class Derived : Base // v1.0{{ public virtual void Foo() public virtual void Foo() {{ Console.WriteLine("Derived.Foo"); Console.WriteLine("Derived.Foo"); }}}}
class Base // v1.0class Base // v1.0{{}}
class Base class Base // v2.0 // v2.0 {{ public virtual void Foo() public virtual void Foo() {{ Database.Log("Base.Foo"); Database.Log("Base.Foo"); }}}}
class Base class Base // v2.0 // v2.0 {{ public virtual public virtual intint Foo() Foo() {{ Database.Log("Base.Foo"); return 0; Database.Log("Base.Foo"); return 0; }}}}
class Derived : Base // v2.0class Derived : Base // v2.0{{ public public newnew virtual void Foo() virtual void Foo() {{ Console.WriteLine("Derived.Foo"); Console.WriteLine("Derived.Foo"); }}}}
class Derived : Base // v2.0class Derived : Base // v2.0{{ public public overrideoverride void Foo() void Foo() {{ super.Foo();super.Foo(); Console.WriteLine("Derived.Foo"); Console.WriteLine("Derived.Foo"); }}}}
Non-virtual methods (C# Precisely section 10.7 and 10.8)
C#: Virtual and non-virtual method example
Unsafe Code – PointersUnsafe Code – PointersDevelopers sometime need total controlDevelopers sometime need total control Performance extremesPerformance extremes Dealing with existing binary structuresDealing with existing binary structures Advanced COM Support, DLL ImportAdvanced COM Support, DLL Import
C# “unsafe” = limited “inline C”C# “unsafe” = limited “inline C” Pointer types, pointer arithmeticPointer types, pointer arithmetic unsafe castsunsafe casts Declarative pinning (fixed statement)Declarative pinning (fixed statement)
Power comes at a price!Power comes at a price! Unsafe means unverifiable codeUnsafe means unverifiable code
Unsafe Code & P/InvokeUnsafe Code & P/Invokeclass FileStream: Stream {
int handle;
public unsafe int Read(byte[] buffer, int index, int count) {
int n = 0;fixed (byte* p = buffer) {
ReadFile(handle, p + index, count, &n, null);}return n;
}
[dllimport("kernel32", SetLastError=true)]static extern unsafe bool ReadFile(
int hFile, void* lpBuffer, int nBytesToRead,int* nBytesRead, Overlapped* lpOverlapped);
}
C# 2.0C# 2.0GenericsGenericsAnonymous methodsAnonymous methodsNullable value typesNullable value typesIteratorsIteratorsPartial typesPartial types……and many moreand many more
GenericsGenericsWhy generics?Why generics? Type safety, performance, increased sharingType safety, performance, increased sharing
C# generics vs. Java genericsC# generics vs. Java generics Exact run-time type information vs. erasureExact run-time type information vs. erasure Entire type system vs. only reference typesEntire type system vs. only reference types Invariant vs. wildcardsInvariant vs. wildcards
public class List<T> public class List<T> {…}{…}List<int> numbers = new List<int>();List<int> numbers = new List<int>();List<Customer> customers = new List<Customer> customers = new List<Customer>();List<Customer>();
public class Listpublic class List{{ private object[] elements;private object[] elements; private int count;private int count;
public void Add(object element) {public void Add(object element) { if (count == elements.Length) Resize(count * 2);if (count == elements.Length) Resize(count * 2); elements[count++] = element;elements[count++] = element; }}
public object this[int index] {public object this[int index] { get { return elements[index]; }get { return elements[index]; } set { elements[index] = value; }set { elements[index] = value; } }}
public int Count {public int Count { get { return count; }get { return count; } }}}}
GenericsGenericspublic class Listpublic class List<<TT>>{{ private private TT[] elements;[] elements; private int count;private int count;
public void Add(public void Add(TT element) { element) { if (count == elements.Length) Resize(count * 2);if (count == elements.Length) Resize(count * 2); elements[count++] = element;elements[count++] = element; }}
public public TT this[int index] { this[int index] { get { return elements[index]; }get { return elements[index]; } set { elements[index] = value; }set { elements[index] = value; } }}
public int Count {public int Count { get { return count; }get { return count; } }}}}
List intList = new List();List intList = new List();
intList.Add(1);intList.Add(1);intList.Add(2);intList.Add(2);intList.Add("Three");intList.Add("Three");
int i = (int)intList[0];int i = (int)intList[0];
List intList = new List();List intList = new List();
intList.Add(1);intList.Add(1); // Argument is boxed // Argument is boxedintList.Add(2);intList.Add(2); // Argument is boxed // Argument is boxedintList.Add("Three");intList.Add("Three"); // Should be an error // Should be an error
int i = (int)intList[0]; // Cast requiredint i = (int)intList[0]; // Cast required
ListList<<intint>> intList = new List intList = new List<<intint>>();();
intList.Add(1);intList.Add(1); // No boxing // No boxingintList.Add(2);intList.Add(2); // No boxing // No boxingintList.Add("Three");intList.Add("Three"); // Compile-time error // Compile-time error
int i = intList[0];int i = intList[0]; // No cast required // No cast required
GenericsGenericsWhy generics?Why generics? Type checking, no boxing, no downcastsType checking, no boxing, no downcasts Reduced code bloat (typed collections)Reduced code bloat (typed collections)
How are C# generics implemented?How are C# generics implemented? Instantiated at run-time, not compile-Instantiated at run-time, not compile-
timetime Checked at declaration, not instantiationChecked at declaration, not instantiation Work for both reference and value typesWork for both reference and value types Complete run-time type informationComplete run-time type information
GenericsGenericsType parameters can be applied toType parameters can be applied to Class, struct, interface, delegate typesClass, struct, interface, delegate types
class Dictionary<K,V> {...}class Dictionary<K,V> {...}
struct HashBucket<K,V> {...}struct HashBucket<K,V> {...}
interface IComparer<T> {...}interface IComparer<T> {...}
delegate R Function<A,R>(A arg);delegate R Function<A,R>(A arg);
Dictionary<string,Customer> customerLookupTable;Dictionary<string,Customer> customerLookupTable;
Dictionary<string,List<Order>> orderLookupTable;Dictionary<string,List<Order>> orderLookupTable;
Dictionary<string,int> wordCount;Dictionary<string,int> wordCount;
GenericsGenericsType parameters can be applied toType parameters can be applied to Class, struct, interface, delegate typesClass, struct, interface, delegate types MethodsMethods
class Utilsclass Utils{{ public static T[] CreateArray<T>(int size) {public static T[] CreateArray<T>(int size) { return new T[size];return new T[size]; }}
public static void SortArray<T>(T[] array) {public static void SortArray<T>(T[] array) { ...... }}}} string[] names = Utils.CreateArray<string>(10);string[] names = Utils.CreateArray<string>(10);
names[0] = "Jones";names[0] = "Jones";......Utils.SortArray(names);Utils.SortArray(names);
GenericsGenericsType parameters can be applied toType parameters can be applied to Class, struct, interface, delegate typesClass, struct, interface, delegate types MethodsMethods
Type parameters can have constraintsType parameters can have constraintsclass Dictionary<K,V>class Dictionary<K,V>{{ public void Add(K key, V value) {public void Add(K key, V value) { ...... if (if (((IComparable)key).CompareTo(x) == 0((IComparable)key).CompareTo(x) == 0) {...}) {...} ...... }}}}
class Dictionary<K,V> class Dictionary<K,V> where K: IComparablewhere K: IComparable{{ public void Add(K key, V value) {public void Add(K key, V value) { ...... if (if (key.CompareTo(x) == 0key.CompareTo(x) == 0) {...}) {...} ...... }}}}
class Dictionary<K,V>: IDictionary<K,V>class Dictionary<K,V>: IDictionary<K,V> where K: IComparable<K>where K: IComparable<K> where V: IKeyProvider<K>, IPersistable, new()where V: IKeyProvider<K>, IPersistable, new(){{ public void Add(K key, V value) { public void Add(K key, V value) { ...... }}}}
GenericsGenericsZero or one primary constraintZero or one primary constraint Actual class, Actual class, classclass, or , or structstruct
Zero or more secondary constraintsZero or more secondary constraints Interface or type parameterInterface or type parameter
Zero or one constructor constraintZero or one constructor constraint new()new()
class Link<T> where T: class {...}class Link<T> where T: class {...}
class Nullable<T> where T: struct {...}class Nullable<T> where T: struct {...}
class Relation<T,U> where T: class where U: T {...}class Relation<T,U> where T: class where U: T {...}
GenericsGenericsCollection classesCollection classes
Collection interfacesCollection interfaces
Collection base classesCollection base classes
Utility classesUtility classes
ReflectionReflection
List<T>List<T>Dictionary<K,V>Dictionary<K,V>SortedDictionary<K,V>SortedDictionary<K,V>Stack<T>Stack<T>Queue<T>Queue<T>
IList<T>IList<T>IDictionary<K,V>IDictionary<K,V>ICollection<T>ICollection<T>IEnumerable<T>IEnumerable<T>IEnumerator<T>IEnumerator<T>IComparable<T>IComparable<T>IComparer<T>IComparer<T>
Collection<T>Collection<T>KeyedCollection<T>KeyedCollection<T>ReadOnlyCollection<T>ReadOnlyCollection<T>
Nullable<T>Nullable<T>EventHandler<T>EventHandler<T>Comparer<T>Comparer<T>
Anonymous MethodsAnonymous MethodsAllows code block in place of delegateAllows code block in place of delegateDelegate type automatically inferredDelegate type automatically inferred Code block can be parameterlessCode block can be parameterless Or code block can have parametersOr code block can have parameters In either case, return types must matchIn either case, return types must match
button.Click += delegate { MessageBox.Show("Hello"); };button.Click += delegate { MessageBox.Show("Hello"); };
button.Click += delegate(object sender, EventArgs e) {button.Click += delegate(object sender, EventArgs e) { MessageBox.Show(((Button)sender).Text); MessageBox.Show(((Button)sender).Text);};};
Nullable TypesNullable TypesSystem.Nullable<T>System.Nullable<T> Provides nullability for any value typeProvides nullability for any value type Struct that combines a T and a boolStruct that combines a T and a bool
public struct Nullable<T> where T: structpublic struct Nullable<T> where T: struct{{ public Nullable(T value) {...}public Nullable(T value) {...} public T Value { get {...} }public T Value { get {...} } public bool HasValue { get {...} }public bool HasValue { get {...} } ......}}
Nullable<int> x = new Nullable<int>(123);Nullable<int> x = new Nullable<int>(123);......if (x.HasValue) Console.WriteLine(x.Value);if (x.HasValue) Console.WriteLine(x.Value);
Nullable TypesNullable TypesT? same as System.Nullable<T>T? same as System.Nullable<T>
null literal conversionsnull literal conversions
Nullable conversionsNullable conversions
int? x = 123;int? x = 123;double? y = 1.25;double? y = 1.25;
int? x = null;int? x = null;double? y = null;double? y = null;
int i = 123;int i = 123;int? x = i;int? x = i; // int --> int?// int --> int?double? y = x;double? y = x; // int? --> double?// int? --> double?int? z = (int?)y;int? z = (int?)y; // double? --> int?// double? --> int?int j = (int)z;int j = (int)z; // int? --> int// int? --> int
Nullable TypesNullable TypesLifted conversions and operatorsLifted conversions and operators
Comparison operatorsComparison operators
Null coalescing operatorNull coalescing operator
int? x = GetNullableInt();int? x = GetNullableInt();int? y = GetNullableInt();int? y = GetNullableInt();int? z = x + y;int? z = x + y;
int? x = GetNullableInt();int? x = GetNullableInt();if (x == null) Console.WriteLine("x is null");if (x == null) Console.WriteLine("x is null");if (x < 0) Console.WriteLine("x less than zero");if (x < 0) Console.WriteLine("x less than zero");
int? x = GetNullableInt();int? x = GetNullableInt();int i = x ?? 0;int i = x ?? 0;
IteratorsIteratorsforeach relies on “enumerator pattern”foreach relies on “enumerator pattern” GetEnumerator() methodGetEnumerator() method
foreach makes enumerating easyforeach makes enumerating easy But enumerators are hard to write!But enumerators are hard to write!
foreach (object obj in list) {foreach (object obj in list) { DoSomething(obj);DoSomething(obj);}}
Enumerator e = list.GetEnumerator();Enumerator e = list.GetEnumerator();while (e.MoveNext()) {while (e.MoveNext()) { object obj = e.Current;object obj = e.Current; DoSomething(obj);DoSomething(obj);}}
IteratorsIteratorspublic class Listpublic class List{{ internal object[] elements;internal object[] elements; internal int count;internal int count;
public IEnumerator GetEnumerator() {public IEnumerator GetEnumerator() { return new ListEnumerator(this); return new ListEnumerator(this); }}}}
public class ListEnumerator : IEnumeratorpublic class ListEnumerator : IEnumerator{{ List list;List list; int index;int index;
internal ListEnumerator(List list) {internal ListEnumerator(List list) { this.list = list;this.list = list; index = -1;index = -1; }}
public bool MoveNext() {public bool MoveNext() { int i = index + 1;int i = index + 1; if (i >= list.count) return false;if (i >= list.count) return false; index = i;index = i; return true;return true; }}
public object Current {public object Current { get { return list.elements[index]; }get { return list.elements[index]; } }}}}
public class Listpublic class List{{ internal object[] elements;internal object[] elements; internal int count;internal int count;
public IEnumerator GetEnumerator() {public IEnumerator GetEnumerator() { for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) { yield return elements[i];yield return elements[i]; }} }}}}
public class Testpublic class Test{{ public IEnumerator GetEnumerator() {public IEnumerator GetEnumerator() { yield return "Hello";yield return "Hello"; yield return "World"; yield return "World"; }}}}
IteratorsIteratorsMethod that incrementally computes Method that incrementally computes and returns a sequence of valuesand returns a sequence of values yield return and yield breakyield return and yield break Must return IEnumerator or IEnumerableMust return IEnumerator or IEnumerable
public IEnumerator GetEnumerator() {public IEnumerator GetEnumerator() { return new __Enumerator(this);return new __Enumerator(this);}}
private class __Enumerator : IEnumeratorprivate class __Enumerator : IEnumerator{{ object current;object current; int state;int state;
public bool MoveNext() {public bool MoveNext() { switch (state) {switch (state) { case 0:case 0: current = "Hello";current = "Hello"; state = 1;state = 1; return true;return true; case 1:case 1: current = "World";current = "World"; state = 2;state = 2; return true;return true; default: default: return false;return false; }} }}
public object Current {public object Current { get { return current; }get { return current; } }}}}
public class List<T>public class List<T>{{ public IEnumerator<T> GetEnumerator() {public IEnumerator<T> GetEnumerator() { for (int i = 0; i < count; i++)for (int i = 0; i < count; i++) yield return elements[i];yield return elements[i]; }}
public IEnumerable<T> Descending() {public IEnumerable<T> Descending() { for (int i = count - 1; i >= 0; i--)for (int i = count - 1; i >= 0; i--) yield return elements[i];yield return elements[i]; }}
public IEnumerable<T> Subrange(int index, int n) {public IEnumerable<T> Subrange(int index, int n) { for (int i = 0; i < n; i++)for (int i = 0; i < n; i++) yield return elements[index + i];yield return elements[index + i]; }}}}
IteratorsIterators
List<Item> items = GetItemList();List<Item> items = GetItemList();foreach (Item x in items) {...}foreach (Item x in items) {...}foreach (Item x in items.Descending()) {...}foreach (Item x in items.Descending()) {...}foreach (Item x in Items.Subrange(10, 20)) {...}foreach (Item x in Items.Subrange(10, 20)) {...}
Partial TypesPartial Typespublic public partialpartial class Customer class Customer{{ private int id;private int id; private string name;private string name; private string address;private string address; private List<Orders> orders;private List<Orders> orders;}}
public public partialpartial class Customer class Customer{{ public void SubmitOrder(Order order) {public void SubmitOrder(Order order) { orders.Add(order);orders.Add(order); }}
public bool HasOutstandingOrders() {public bool HasOutstandingOrders() { return orders.Count > 0;return orders.Count > 0; }}}}
public class Customerpublic class Customer{{ private int id;private int id; private string name;private string name; private string address;private string address; private List<Orders> orders;private List<Orders> orders;
public void SubmitOrder(Order order) public void SubmitOrder(Order order) {{ orders.Add(order);orders.Add(order); }}
public bool HasOutstandingOrders() {public bool HasOutstandingOrders() { return orders.Count > 0;return orders.Count > 0; }}}}
Static ClassesStatic ClassesOnly static membersOnly static membersCannot be used as type of variable, Cannot be used as type of variable, parameter, field, property, …parameter, field, property, …Examples include System.Console, Examples include System.Console, System.EnvironmentSystem.Environmentpublic public staticstatic class Math class Math{{ public static double Sin(double x) {...}public static double Sin(double x) {...} public static double Cos(double x) {...}public static double Cos(double x) {...} ......}}
ComparisonComparisonJava, C# and C++Java, C# and C++