Introduction to C# (Part 2)
Introduction
• At the end of this lecture you will be able to:– Compare and understand the some of the differences between C# and C++.
– Understand the syntax and usage of the different aspects of the C# language
References
• Nagel, Christian et al, Professional C# 2005, Wrox Press, 2005– Chapter 1, Appendix D
• Chapter 5 — Improving Managed Code Performance :– http://msdn2.microsoft.com/en-us/library/ms998547.aspx
• Rico Mariani's Performance Tidbits: Performance Quiz #11: Ten Questions on Value-Based Programming– http://blogs.gotdotnet.com/ricom/archive/2006/08/31/performance-
quiz-11-ten-questions-on-value-based-programming.aspx
• Rico Mariani's Performance Tidbits: Six Questions about Generics and Performance– http://blogs.gotdotnet.com/ricom/archive/2004/09/13/229025.aspx
Arrays
• Are proper System.Object derived classes, not simply a contiguous chunk of memory as in C++
double [] array; // Simply declares a reference without actually // instantiating an array. array = new double[10]; // Actually instantiates a System.Array object, // and gives it size 10.
• Shortcut:double [] array = new double[10];
Arrays
• Arrays are sized only when instanced, the declaration [ ] indicates rank
• Explicit initialisation:
double [] array = new double[10] {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0};
double [] array = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0};
• If not explicitly initialised, default constructor is called
Arrays
• Can use .Length property to determine size
for (int i=0; i<array.Length; i++)
array[i] *= 2.0f;
Arrays
• Multi-dimensional Rectangular:
int [,] myArray2d; myArray2d = new int[2,3] { {1, 0}, {3, 6}, {9, 12} };
int [,,] myArray3d = new int[2,3,2];
• Indexed:
int x = myArray3d[1,2,0] + myArray2d[0,1];
Arrays
• Jagged arrays
int [][] myJaggedArray = new int[3][];
for (int i=0; i<3; i++)
myJaggedArray[i] = new int[2*i + 2]; • Indexed:
int x = myJaggedArray[1][3];
Arrays
• Bounds checking is performed automatically by the runtime
• IndexOutOfBoundsException will be thrown• Arrays are not resizable after they are defined, to
use resizable lists etc. consider a class in the System.Collections namespace
• Jagged arrays offer performance benefits over mutlidimensional arrays due to MSIL optimisations.
• However jagged arrays are not CLS compliant and so cannot be used across languages ( OK for private classes and assemblies though ).
Enumerations
enum TypeOfBuilding {Shop, House, OfficeBlock, School}
• Numbering elements:enum TypeOfBuilding {Shop, House=5, OfficeBlock, School=10}
// Shop will have value 0, OfficeBlock will have value 6
• Name of enumeration must be used to access:TypeOfBuilding MyHouse = TypeOfBuilding.House
Enumerations
• Can use methods derived from the System.enum classTypeOfBuilding MyHouse = TypeOfBuilding.House;
string Result = MyHouse.ToString(); // Result will contain "House"
TypeOfBuilding MyHouse = (TypeOfBuilding)Enum.Parse(typeof(TypeOfBuilding), "House", true);
• Select underlying type to store enumerated dataenum TypeOfBuilding : short {Shop, House, OfficeBlock, School};
• Defaults to int
Exceptions
try { // normal code
} catch (MyException e) // MyException derived from System.Exception { // error handling code
} // optionally further catch blocks finally { // clean up code}
Exceptions
• Exceptions must be derived from System.Exception class• finally block contains code which is always executed after
the try block, regardless of whether any exceptions were thrown
• It is optional• Useful for cleaning up resources allocated in try block• Also useful for control flow
Structs
• Same syntax as classes except keyword struct replaces class
• Structs are value types which are created on the stack
• Has a default, non-overridable, no-parameter constructor which zero out all member variables
• Other parameter constructors can be defined
• Must be initialised with new
Classes vs Structs
• Consider using Classes when:–There will be subtyping–Synchronisation.–We are interested in keeping track of special instances
which have their own ‘identity’–e.g. RenderSystem
• Consider using Structs when:–None of the class benefits above apply.–Large collections of this type are required and will be
iterated through.–e.g. Point3D struct.
Constants• Constant member variables:class MyClass { public const int MyConstant = 2;
}int SomeVariable = MyClass.MyConstant; • Static Constants:class MyClass { public static readonly int MyConstant; static MyClass() {
// work out and assign the initial value of MyConstant here }
}
Constants
• Instance Constants:class MyClass { public readonly int MyConstInst; MyClass() {
// work out and initialize MyConstInst here }
}• const keyword define value at compile time, readonly keyword
defines value at runtime (hence enable setting of values in static and non-static constructors)
Operator Overloading
public static MyClass operator + (MyClass lhs, MyClass rhs)
{ MyClass Result = new MyClass(); Result.x = lhs.x + rhs.x; return Result;
}
Operator Overloading
• Can overload the following operators:– Binary arithemetic: +, -, /, *, %
– Unary operators: ++, -- (prefix only)
– Comparison Operators: !=, ==, <, >, <=, >=
– Bitwise operators: &, |, ~, ^, !
– Boolean value: true, false
Operator Overloading
• Cannot override the following:–Arithmetic assignment: +=, -=, *=, /=, %=, these are
worked out automatically based on the arithmetic operators
–Postfix increment operators, these are worked out by calling the prefix increment but returning the old value
–Bitwise assignment operators: &=, |=, ^=, >>=, <<=–Boolean operators: &&, ||, these are worked out based
on bitwise operators–Assignment operator: =, the meaning of this is fixed
• Must override in pairs: == and !=, < and >, <= and >=
Indexers
class MyClass { public long this[int x] {
get {
// code to get element } set {
// code to set element. eg. X = value;
} } // etc.
Indexers
• Can’t override [ ] operator
• Indexers allow similar functionality
• Parameter in [ ] can be of any type
• set is called when [ ] operator is to the left of an assignment
• get is called when [ ] operator is to the right of an assignment
Casting Operators
public static implicit operator MyDest (MySource Source)
{ // code to do cast. Must return a MyDest instance
} • Must be defined static• implicit: for use implicitly, should always work• explicit: for use explicitly, may result in loss of
data or thrown exception
Casting Operators
• C# inherently supports casting between base and derived classes, users cannot define these cast operators
• Will throw an exception if casting from base to derived• Using as keyword returns null if cast fails, no thrown
exception// assume MyDerivedClass is derived from MyBaseClass
MyBaseClass MyBase = new MyBaseClass(); MyDerivedClass MyDerived as (MyDerivedClass) MyBase; // this will return null
Pointers and Unsafe Code
• Pointers exist in C# and can be used inside an unsafe code block• Methods:public unsafe void MyMethod() { • Classes / Structs:unsafe class MyClass {
– All members will be regarded as unsafe• Member variables:private unsafe int* pX; • Code block:unsafe { // statements that use pointers
}
Pointers and Unsafe Code
• Not permitted to dereference or perform arithmetic operations on void* pointers
• Pointers cannot point to reference classes
• Must also specify /unsafe flag as a compiler option
• Can point to value data inside reference classes if contained within a fixed block
Fixing Data on the Heap
class MyClass { public int X; // etc.
} // Elsewhere in your code ... MyClass Mine = new MyClass(); // Do processing fixed(int *pX = Mine.X) { // Can use pX in this block. }// nestedfixed(int *pX = Mine.X, *pX2 = Mine2.X) {}
Fixing Data on the Heap
• Stops Garbage Collector from moving this object around on the heap for the duration of the fixed block
• Needed so that the pointer can be correctly dereferenced to the right data
Arrays on the Stack
• Low overhead, very similar to C++ arrays
ulong *pMyArray = stackalloc ulong [20]; • Can specify size at runtime
int X;
// Initialize X
ulong *pMyArray = stackalloc ulong [X];
Interfaces
• Similar to abstract classes
interface IMyInterface
{
void MyMethod(int X);
}• No access modifiers
• No implementation
Interfaces
• Classes can derive from one or more interfaces (called implementing)
class MyClass : MyBaseClass, IMyInterface, IAnotherInterface // etc
{ public virtual void MyMethod(int X) {
// implementation }
// etc.
Interfaces
• Interfaces can derive from one or more interfaces
• Can cast classes to interfaces
Delegates
• Like function pointers in C++, but can refer to instance methodsclass MyClass { void MyMethod(int X) { // etc. }
}MyClass Mine = new MyClass(); // Instantiate a MyOp delegate. Set it to point to the MyMethod method
// of Mine. MyOp DoIt = new MyOp(Mine.MyMethod); DoIt(10);
Delegates
// Define a delegate class that represents a method that takes an int and
// returns void
delegate void MyOp(int X); • Definition of delegate class must include full signature of the
wrapped method
Delegates
• Multicast delegates: with void return types
• More than one method can be wrapped within the delegate using the += and -= operators
• Invoking the delegate calls all the methods wrapped within it
Events
• Special form of delegates supporting the callback event notification model
delegate void EventClass(obj Sender, EventArgs e);
• Delcaration:public event EventClass OnClickEvent;• Adding handlers:EventSource.OnClickEvent += MyHandler;• Alerting handlers: OnClickEvent(this, new EventArgs();
Generics
• New to C# .NET 2.0• Similar to C++ templatespublic class MyGeneric<T> { private T element; public T Method(T parm) {
return null; }
}
Generics• However, if class members of T were accessed within the class, we must
specify either a base class or interface that T derives from.public interface IDemo { void Demo();
} public class MyGeneric<T> where T : IDemo, new() { public void Method() {
T obj = new T(); obj.Demo();
} }
Generics
• The where clause specifies the interfaces and base classes that the T class must derive from
• The new() specifies that the T class must contain a default constructor
• Prefer using Generic container classes over the older style container classes such as ArrayList for type safety and performance benefits.
Attributes
• Classes which apply to code elements, used for generation documentation or additional compiled code settings
• Syntax:[Conditional("Debug")] void DisplayValuesOfImportantVariables() { // etc.
• Included with [ ] before the code element it is applied to
Attributes
• Examples:– Conditional: Only compiles if symbol is defined by preprocessor
– DllImport: Method is defined in external DLL
– StructLayout: Contents of struct to be layed out in memory, like C++ union
– Obsolete: Compiler generates warning if this method is used
Preprocessor Directives
• Reduced subset of C++’s• #include not supported (not required)• #define, #undef
–Same as C++, though must occur before any C# code
• #if, #elif, #else, #endif, #line, #warning, #error–Same as C++
• #region, #endregion–To block off regions of code, for collapse/expansion
formatting by IDEs
Review
• Compare and understand the some of the differences between C# and C++.
• Understand the syntax and usage of the different aspects of the C# language