Examples for C# Essentials
http://oreilly.com/catalog/csharpess/examples/
Introduction
A Minimal C# Program
class Test { static void Main() { System.Console.WriteLine("Welcome to C#!"); } }
C# Language Reference
Identifiers
Ko|n @Ko|n
Types
Example: Building and Using Types// Imports types from System namespace, such as Console using System; class Counter { // New types are typically classes or structs // --- Data members --- int value; // field of type int int scaleFactor; // field of type int // Constructor, used to initialize a type instance public Counter(int scaleFactor) { this.scaleFactor = scaleFactor; } // Method public void Inc() { value+=scaleFactor; } // Property public int Count { get {return value; } } } class Test { // Execution begins here static void Main() { // Create an instance of counter type Counter c = new Counter(5); c.Inc(); c.Inc(); Console.WriteLine(c.Count); // prints "10"; // create another instance of counter type Counter d = new Counter(7); d.Inc(); Console.WriteLine(d.Count); // prints "7"; } }Implicit and Explicit Conversions
int x = 123456; // int is a 4-byte integer long y = x; // implicit conversion to 8-byte integer short z =(short)x // explicit conversion to 2-byte integerPredefined Types
int i = 5; System.Int32 i = 5;Integral Types
int x = 5; ulong y = 0x1234AF; // prefix with 0x for hexadecimal int x = 123456; long y = x; // implicit, no information lost short z = (short)x; // explicit, truncates xFloating Point Types
float x = 9.81f; double y = 7E-02; // 0.07 int strength = 2; int offset = 3; float x = 9.53f * strength - offset; float x = 3.53f; int offset = (int)x;Decimal Type
decimal x = 80603.454327m; // holds exact valueChar Type
'A' // simple character '\u0041' // Unicode '\x0041' // unsigned short hexadecimal '\n' // escape sequence characterString Type
string a = "Heat"; string a1 = "\\\\server\\fileshare\\helloworld.cs"; string a2 = @"\\server\fileshare\helloworld.cs"; Console.WriteLine(a1==a2); // Prints "True" string b1 = "First Line\r\nSecond Line"; string b2 = @"First Line Second Line"; Console.WriteLine(b1==b2); // Prints "True"Types and Memory
Simple Types Are Value Types
int i = 3; string s = i.ToString(); // This is an explanatory version of System.Int32 namespace System { struct Int32 { ... public string ToString() { return ...; } } } // This is valid code, but we recommend you use the int alias System.Int32 i = 5;Value Types and Reference Types Side By Side
// Reference-type declaration class PointR { public int x, y; } // Value-type declaration struct PointV { public int x, y; } class Test { static void Main() { PointR a; // Local reference-type variable, uses 4 bytes of // memory on the stack to hold address PointV b; // Local value-type variable, uses 8 bytes of // memory on the stack for x and y a = new PointR(); // Assigns the reference to address of new // instance of PointR allocated on the // heap. The object on the heap uses 8 // bytes of memory for x and y, and an // additional 8 bytes for core object // requirements, such as storing the // object's type synchronization state b = new PointV(); // Calls the value-type's default // constructor. The default constructor // for both PointR and PointV will set // each field to its default value, which // will be 0 for both x and y. a.x = 7; b.x = 7; } } // At the end of the method the local variables a and b go out of // scope, but the new instance of a PointR remains in memory until // the garbage collector determines it is no longer referenced ... PointR c = a; PointV d = b; c.x = 9; d.x = 9; Console.WriteLine(a.x); // Prints 9 Console.WriteLine(b.x); // Prints 7 } }Type System Unification
Value Types "Expand The Set Of Simple Types"
int[] iarr = new int [1000]; struct PointV { public int x, y } PointV[] pvarr = new PointV[1000]; class PointR { public int x, y; } PointR[] prarr = new PointR[1000]; for( int i=0; i<prarr.Length; i++ ) prarr[i] = new PointR();Boxing and Unboxing Value Types
class Queue { ... void Enqueue(object o) {...} object Dequeue() {return ...} } Queue q = new Queue(); q.Enqueue(9); // box the int int i = (int)q.Dequeue(); // unbox the int
Variables
Definite Assignmentusing System; class Test { int v; // Constructors that initalize an instance of a Test public Test() {} // v will be automatically assigned to 0 public Test(int a) { // explicitly assign v a value v = a; } static void Main() { Test[] iarr = new Test [2]; // declare array Console.WriteLine(iarr[1]); // ok, elements assigned to null Test t; Console.WriteLine(t); // error, t not assigned } }Default Values
int a = 1000000; int b = 1000000; // Check an expression int c = checked(a*b); // Check every expression in a statement-block checked { ... c = a * b; ... } const int signedBit = unchecked((int)0x80000000);
Statements
Expression Statementsint x = 5 + 6; // assign result x++; // side effect int y = Math.Min(x, 20); // side effect and assign result Math.Min (x, y); // discards result, but ok, there is a side effect x == y; // error, has no side effect, and does not assign resultDeclaration Statements
bool a = true; while(a) { int x = 5; if (x==5) { int y = 7; int x = 2; // error, x already defined } Console.WriteLine(y); // error, y is out of scope } const double speedOfLight = 2.99792458E08; speedOfLight+=10; // errorEmpty Statements
while(!thread.IsAlive);Selection Statements
If-Else Statement
int Compare(int a, int b) { if (a>b) return 1; else if (a<b) return -1; return 0; }Switch Statement
void Award(int x) { switch(x) { case 1: Console.WriteLine("Winner!"); break; case 2: Console.WriteLine("Runner-up"); break; case 3: case 4: Console.WriteLine("Highly commended"); break; default: Console.WriteLine("Don't quit your day job!"); break; } } void Greet(string title) { switch (title) { case null: Console.WriteLine("And you are?"); goto default; case "King": Console.WriteLine("Greetings your highness"); // error, should specify break, otherwise... default : Console.WriteLine("How's it hanging?"); break; } }Loop Statements
While Loops
int i = 0; while (i<5) { i++; }Do-While Loops
int i = 0; do i++; while (i<5);For Loops
for (int i=0; i<10; i++) Console.WriteLine(i); for (;;) Console.WriteLine("Hell ain't so bad");Foreach Loops
foreach ( type-value in IEnumerable )
statement or statement-block
for (int i=0; i<dynamite.Length; i++) Console.WriteLine(dynamite [i]); foreach (Stick stick in dynamite) Console.WriteLine(stick); IEnumerator ie = dynamite.GetEnumerator(); while (ie.MoveNext()) { Stick stick = (Stick)ie.Current; Console.WriteLine(stick); }Jump Statements
Break Statement
int x = 0; while (true) { x++; if (x>5) break; // break from the loop }Continue Statement
int x = 0; int y = 0; while (y<100) { x++; if ((x%7)==0) continue; // continue with next iteration y++; }Goto Statement
int x = 4; start: x++; if (x==5) goto start;Return Statement
int CalcX(int a) { int x = a * 100; return x; // return to the calling method with value }Throw Statement
if (w==null) throw new Exception("w can't be null");
Organizing Types
Namespacesnamespace MyCompany.MyProduct.Drawing { class Point {int x, y, z} delegate void PointInvoker(Point p); }Nesting Namespaces
namespace MyCompany { namespace MyProduct { namespace Drawing { class Point {int x, y, z} delegate void PointInvoker(Point p); } } }Using A Type With Its Fully Qualified Name
namespace TestProject { class Test { static void Main() { MyCompany.MyProduct.Drawing.Point x; } } }Using Keyword
namespace TestProject { using MyCompany.MyProduct.Drawing; class Test { static void Main() { Point x; } } }Aliasing Types and Namespaces
using sys = System; // Namespace alias using txt = System.String; // Type alias class Test { static void Main() { txt s = "Hello, World!"; sys.Console.WriteLine(s); // Hello, World! sys.Console.WriteLine(s.GetType()); // System.String } }
Inheritance
class Location { // Implicitly inherits from object string name; // The constructor that initializes Location public Location(string name) { this.name = name; } public string Name {get {return name;}} public void Display() { Console.WriteLine(Name); } } class URL : Location { // Inherit from Location public void Navigate() { Console.WriteLine("Navigating to "+Name); } // The constructor for URL, which calls Location's constructor public URL(string name) : base(name) {} } : class Test { static void Main() { URL u = new URL("http://microsoft.com"); u.Display(); u.Navigate(); } }Class Conversions
URL u = new URL(); Location l = u; // upcast u = (URL)l; // downcastAs Operator
u = l as URL;Is Operator
if (l is URL) ((URL)l).Navigate();Polymorphism
class LocalFile : Location { public void Execute() { Console.WriteLine("Executing "+Name); } // The constructor for LocalFile, which calls URL's constructor public LocalFile(string name) : base(name) {} } class Test { static void Main() { URL u = new URL(); LocalFile l = new LocalFile(); Show(u); Show(l); } public static void Show(Location loc) { Console.Write("Location is: "); loc.Display(); } }Virtual Function Members
class Location { public virtual void Display() { Console.WriteLine(Name); } ... } class URL : Location { // chop off the http:// at the start public override void Display() { Console.WriteLine(Name.Substring(6)); } ... }Abstract Classes and Abstract Members
abstract class Location { public abstract void Launch(); } class URL : Location { public override void Launch() { Console.WriteLine("Run Internet Explorer..."); } } class LocalFile : Location { public override void Launch() { Console.WriteLine("Run Win32 Program..."); } }Sealed Classes
sealed class Math { ... }Hiding Inherited Members
class B { public virtual void Foo() {} } class D : B { public override void Foo() {} } class N : D { public new void Foo() {} // hides D's Foo } N n = new N(); n.Foo(); // calls N's Foo ((D)n).Foo(); // calls D's Foo ((B)n).Foo(); // calls D's FooVersioning Virtual Function Members
class B { // written by the library people virtual void Foo() {...} // added in latest update } class D : B { // written by you void Foo() {...} }
Access Modifiers
// Assembly1.dll using System; public class A { private int x=5; public void Foo() {Console.WriteLine (x);} protected static void Goo() {} protected internal class NestedType {} } internal class B { private void Hoo () { A a1 = new A (); // ok Console.WriteLine(a1.x); // error, A.x is private A.NestedType n; // ok, A.NestedType is internal A.Goo(); // error, A's Goo is protected } } // Assembly2.exe (references Assembly1.dll) using System; class C : A { // C defaults to internal static void Main() { // Main defaults to private A a1 = new A(); // ok a1.Foo(); // ok C.Goo(); // ok, inherits A's protected static member new A.NestedType(); // ok, A.NestedType is protected new B(); // error, Assembly 1's B is internal Console.WriteLine(x); // error, A's x is private } }Restrictions on Access Modifiers
Classes and Structs
Instance Members and Static Membersclass Panda { string name; static string speciesName = "Ailuropoda melanoleuca"; // Initializes Panda(See Instance Constructors) public Panda(string name) { this.name = name; } public void PrintName() { Console.WriteLine(name); } public static void PrintSpeciesName() { Console.WriteLine(speciesName); } } class Test { static void Main() { Panda.PrintSpeciesName(); // invoke static method Panda p = new Panda("Petey"); p.PrintName(); // invoke instance method } }Fields
class MyClass { int x; float y = 1, z = 2; static readonly int MaxSize = 10; ... }Constants
public static double Circumference(double radius) { return 2 * Math.PI * radius; } public static double Circumference(double radius) { return 6.2831853071795862 * radius; }Properties
public class Well { decimal dollars; // private field public int Cents { get { return(int)(dollars * 100); } set { // value is an implicit variable in a set if (value>=0) // typical validation code dollars = (decimal)value/100; } } } class Test { static void Main() { Well w = new Well(); w.Cents = 25; // set int x = w.Cents; // get w.Cents += 10; // get and set(throw a dime in the well) } }Indexers
public class ScoreList { int[] scores = new int [5]; // indexer public int this[int index] { get { return scores[index]; } set { if(value >= 0 && value <= 10) scores[index] = value; } } // property (read-only) public int Average { get { int sum = 0; foreach(int score in scores) sum += score; return sum / scores.Length; } } } class IndexerTest { static void Main() { ScoreList sl = new ScoreList(); sl[0] = 9; sl[1] = 8; sl[2] = 7; sl[3] = sl[4] = sl[1]; System.Console.WriteLine(sl.Average); } }Methods
Passing Arguments By Value
static void Foo(int p) {++p;} static void Main() { int x = 8; Foo(x); // make a copy of the value-type x Console.WriteLine(x); // x will still be 8 }Ref Modifier
static void Foo(ref int p) {++p;} static void Test() { int x = 8; Foo(ref x); // send reference of x to Foo Console.WriteLine(x); // x is now 9 }Out Modifier
using System; class Test { static void Split(string name, out string firstNames, out string lastName) { int i = name.LastIndexOf(' '); firstNames = name.Substring(0, i); lastName = name.Substring(i+1); } static void Main() { string a, b; Split("Nuno Bettencourt", out a, out b); Console.WriteLine("FirstName:{0}, LastName:{1}", a, b); } }Params Modifier
using System; class Test { static int Add(params int[] iarr) { int sum = 0; foreach(int i in iarr) sum += i; return sum; } static void Main() { int i = Add(1, 2, 3, 4); Console.WriteLine(i); // 10 } }Overloading Methods
void Foo(int x); viod Foo(double x); void Foo(int x, float y); void Foo(float x, int y); void Foo(ref int x); void Foo(out int x); void Foo(int x); float Foo(int x); // compile error void Goo (int[] x); void Goo (params int[] x); // compile errorOperators
Implementing Value Equality
class Note { int value; public Note(int semitonesFromA) { value = semitonesFromA; } public static bool operator ==(Note x, Note y) { return x.value == y.value; } public static bool operator !=(Note x, Note y) { return x.value != y.value; } public override bool Equals(object o) { if(!(o is Note)) return false; return this ==(Note)o; } } Note a = new Note(4); Note b = new Note(4); Object c = a; Object d = b; // To compare a and b by reference Console.WriteLine((object)a ==(object)b; // false //To compare a and b by value: Console.WriteLine(a == b); // true //To compare c and d by reference: Console.WriteLine(c == d); // false //To compare c and d by value: Console.WriteLine(c.Equals(d)); // trueCustom Implicit and Explicit Conversions
... // Convert to hertz public static implicit operator double(Note x) { return 440*Math.Pow(2,(double)x.value/12); } // Convert from hertz(only accurate to nearest semitone) public static explicit operator Note(double x) { return new Note((int)(0.5+12*(Math.Log(x/440)/Math.Log(2)))); } ... Note n =(Note)554.37; // explicit conversion double x = n; // implicit conversionThree-State Logic Operators
public struct SQLBoolean ... { ... public static bool operator true(SQLBoolean x) { return x.value == 1; } public static bool operator false(SQLBoolean x) { return x.value == -1; } public static SQLBoolean operator !(SQLBoolean x) { return new SQLBoolean(- x.value); } public bool IsNull { get { return value == 0;} } ... } class Test { void Foo(SQLBoolean a) { if (a) Console.WriteLine("True"); else if (! a) Console.WriteLine("False"); else Console.WriteLine("Null"); } }Instance Constructors
class MyClass { public MyClass() { // initialization code } } class MyClass { public int x; public MyClass() : this(5) {} public MyClass(int v) { x = v; } } MyClass m1 = new MyClass(); MyClass m2 = new MyClass(10); Console.WriteLine(m1.x) // 5 Console.Writeline(m2.x) // 10;Calling Base Class Constructors
class B { public int x ; public B(int a) { x = a; } public B(int a, int b) { x = a * b; } // Notice how all of B's constructors need parameters } class D : B { public D() : this(7) {} // call an overloaded constructor public D(int a) : base(a) {} // call a base class constructor }Field Initialization Order
class MyClass { int x = 5; }Static Constructors
class Test { static Test() { Console.WriteLine("Test Initialized"); } }Static Field Initialization Order
class Test { public static int x = 5; public static void Foo() {} static Test() { Console.WriteLine("Test Initialized"); } }Non-Determinism Of Static Constructor Calls
class Test2 { public static void Foo() {} static Test() { Console.WriteLine("Test2 Initialized"); } } Test.Foo(); Test2.Foo();Self Referencing
this Keyword
class Dude { string name; public Test(string name) { this.name = name; } public void Introduce(Dude a) { if (a!=this) Console.WriteLine("Hello, I'm "+name); } }Base Keyword
class Hermit : Dude { public void new Introduce(Dude a) { base.TalkTo(a); Console.WriteLine("Nice Talking To You"); } }Destructors and Finalizers
protected override void Finalize() { ... base.Finalize(); }Nested Types
using System; class A { int x = 3; // private member protected internal class Nested {// choose any access-level public void Foo () { A a = new A (); Console.WriteLine (a.x); //can access A's private members } } } class B { static void Main () { A.Nested n = new A.Nested (); // Nested is scoped to A n.Foo (); } } // an example of using "new" on a type declaration class C : A { new public class Nested {} // hide inherited type member }
Interfaces
Defining an Interfacepublic interface IDelete { void Delete(); }Implementing an Interface
public class TextBox : IDelete { public void Delete() {...} } public class TreeView : IDelete { public void Delete() {...} } public class TextBox : Control, IDelete {...} public class TreeView : Control, IDelete {...}Using an Interface
class MyForm { ... void DeleteClick() { if (ActiveControl is IDelete) { IDelete d = (IDelete)ActiveControl; d.Delete(); } } }Extending an Interface
ISuperDelete : IDelete { bool CanDelete {get;} event EventHandler CanDeleteChanged; }Explicit Interface Implementation
public interface IDesignTimeControl { ... object Delete(); } public class TextBox : IDelete, IDesignTimeControl { ... void IDelete.Delete() {} object IDesignTimeControl.Delete() {...} // Note that explicitly implementing just one of them would // be enough to resolve the conflict } TextBox tb = new TextBox(); IDesignTimeControl idtc = (IDesignTimeControl)tb; IDelete id = (IDelete)tb; idtc.Delete(); id.Delete();Reimplementing An Interface
public class RichTextBox : TextBox, IDelete { // TextBox's IDelete.Delete is not virtual (since explicit // interface implementations cannot be virtual) public void Delete() {} }Interface Conversions
interface IDelete {...} interface IDesigntimeControl {...} class TextBox : IDelete, IDesignTimeControl {...} sealed class Timer : IDesignTimeControl {...} TextBox tb1 = new TextBox (); IDelete d = tb1; // implicit cast IDesignTimeControl dtc = (IDesignTimeControl)d; TextBox tb2 = (TextBox)dtc; Timer t = (Timer)d; // illegal, a Timer can never implement IDelete
Arrays
char[] vowels = new char[] {'a','e','i','o','u'}; Console.WriteLine(vowels [1]); // Prints "e"Multi-Dimensional Arrays
// rectangular int [,,] matrixR = new int [3, 4, 5]; // creates 1 big cube // jagged int [][][] matrixJ = new int [3][][]; int [][][] matrixJ = new int [3][][]; for (int i = 0; i < 3; i++) { matrixJ[i] = new int [4][]; for (int j = 0; j < 4; j++) matrixJ[i][j] = new int [5]; } // assign an element matrixR [1,1,1] = matrixJ [1][1][1] = 7;Local and Field Array Declarations
// single dimensional for(int i = 0; i < vowels.Length; i++); // multi-dimensional for(int i = 0; i < matrixR.GetLength(2); i++);Bounds Checking
Enums
public enum Direction {North, East, West, South} Direction walls = Direction.East; [Flags] public enum Direction : byte { North=1, East=2, West=4, South=8 } Direction walls = Direction.North | Direction.West; if((walls & Direction.North) != 0) System.Console.WriteLine("Can't go north!"); Console.WriteLine(walls.Format()); // Displays "North|West" Console.WriteLine(walls); // Calls walls.ToString, displays "5" using System; public enum Toggle : byte { Off=0, On=1 } class TestEnum { static void Main() { Type t = Enum.GetUnderlyingType(typeof(Toggle)); Console.WriteLine(t); // Prints "Byte" bool bDimmed = Enum.IsDefined(typeof(Toggle), "Dimmed"); Console.WriteLine(bDimmed); // Prints "False" Toggle tog =(Switch)Enum.FromString(typeof(Toggle), "On"); Console.WriteLine(tog); // Prints "1" Console.WriteLine(tog.Format()); // Prints "On" object[] oa = Enum.GetValues(typeof(Toggle)); foreach(Toggle tog in oa) // Prints "On=1, Off=0" Console.WriteLine("{0}={1}", tog.Format(), tog); } }
Delegates
delegate bool Filter(string s); class Test { static void Main() { Filter f = new Filter(FirstHalfOfAlphabet); Display(new String [] {"Ant","Lion","Yak"}, f); } static bool FirstHalfOfAlphabet(string s) { return "N".CompareTo(s) > 0; } static void Display(string[] names, Filter f) { int count = 0; foreach(string s in names) if(f(s)) // invoke delegate Console.WriteLine("Item {0} is {1}", count++, s); } }Multicast Delegates
delegate void MethodInvoker(); class Test { static void Main() { new Test(); // prints "Foo","Goo" } Test() { MethodInvoker m = null; m += new MethodInvoker(Foo); m += new MethodInvoker(Goo); m(); } void Foo() { Console.WriteLine("Foo"); } void Goo() { Console.WriteLine("Goo"); } } Test { MethodInvoker m = null; m += new MethodInvoker(Foo); m -= new MethodInvoker(Foo); // m is now null }Delegates Compared With Interfaces
interface IFilter { bool Filter(string s); } class Test { class FirstHalfOfAlphabetFilter : IFilter { public bool Filter(string s) { return ("N".CompareTo(s) > 0); } } static void Main() { FirstHalfOfAlphabetFilter f = new FirstHalfOfAlphabetFilter(); Display(new string [] {"Ant", "Lion", "Yak"}, f); } static void Display(string[] names, IFilter f) { int count = 0; foreach (string s in names) if (f.Filter(s)) Console.WriteLine("Item {0} is {1}", count++, s); } }
Events
Defining a Delegate for an Eventdelegate void MoveEventHandler(object source, MoveEventArgs e);Storing Data for an Event with EventArgs
public class MoveEventArgs : EventArgs { public int newPosition; public bool cancel; public MoveEventArgs(int newPosition) { this.newPosition = newPosition; } }Declaring and Firing an Event
class Slider { int position; public event MoveEventHandler Move; public int Position { get { return position; } set { if (position != value) { // if position changed if (Move != null) { // if invocation list not empty MoveEventArgs args = new MoveEventArgs(value); Move(this, args); // fire event if (args.cancel) return; } position = value; } } } }Acting on an Event with Event Handlers
class Form { static void Main() { Slider slider = new Slider(); // register with the Move event slider.Move += new MoveEventHandler(slider_Move); slider.Position = 20; slider.Position = 60; } static void slider_Move(object source, MoveEventArgs e) { if(e.newPosition < 50) Console.WriteLine("OK"); else { e.cancel = true; Console.WriteLine("Can't go that high!"); } } }Events As Properties
public event MoveEventHandler Move { get { return (MoveEventHandler)myEventStorer["Move"]; } set { myEventStore ["Move"] = value; } }
Try Statements and Exceptions
Exceptionspublic class File { ... public static StreamWriter CreateText(string s) { ... if (!Valid(s)) throw new IOException("Couldn't create...", ...); ... } } class Test { ... void Foo(object x) { StreamWriter sw = null; try { sw = File.CreateText("foo.txt"); sw.Write(x.ToString()); } catch(IOException ex) { Console.WriteLine(ex); } finally { if(sw != null) sw.Close(); } } }Catch Statement
catch(IOException) { // don't specify variable Console.WriteLine("Couldn't create the foo!"); }Catching System.Exception
catch { Console.WriteLine("Couldn't create the foo!"); }Specifying Multiple Catch Clauses
try {...} catch (NullReferenceException) {...} catch (IOException) {...} catch {...}
Attributes
Attribute Classes[Serializable] public class Foo {...} class SerializableAttribute : Attribute {...} [System.SerializableAttribute] public class Foo {...}Named and Positional Parameters
[Obsolete("Use Bar class instead", IsError=true)] public class Foo {...}Attribute Targets
[assembly:CLSCompliant(true)]Specifying Multiple Attributes
[Serializable, Obsolete, CLSCompliant(false)] public class Bar {...} [Serializable] [Obsolete] [CLSCompliant(false)] public class Bar {...} [Serializable, Obsolete] [CLSCompliant(false)] public class Bar {...}
Unsafe Code and Pointers
Unsafe Codeunsafe void RedFilter(int[,] bitmap) { const int length = bitmap.Length; fixed (int* b = bitmap) { int* p = b; for(int i = 0; i < length; i++) *p++ &= 0xFF; } }Fixed Statement
class Test { int x; static void Main() { Test test = new Test(); unsafe { fixed(int* p = &test.x) { // pins Test *p = 9; } System.Console.WriteLine(test.x); } } }Pointer to Member Operator
struct Test { int x; unsafe static void Main() { Test test = new Test(); Test* p = &test; p->x = 9; System.Console.WriteLine(test.x); } }The stackalloc Keyword
int* a = stackalloc int [10]; for (int i = 0; i < 10; ++i) Console.WriteLine(a[i]); // print raw memoryPre-Processor Directives
#define DEBUG class MyClass { int x; void Foo() { # if DEBUG Console.WriteLine("Testing: x = {0}", x); # endif ... } #define DEBUG = true
XML Documentation
C/C++-Style Commentsint x = 3; // this is a comment MyMethod(); /* this is a comment that spans two lines */Documentation Comments
// Filename: DocTest.cs using System; class MyClass { /// <summary> /// The Foo method is called from /// <see cref="Main">Main</see> /// </summary> /// <mytag>Secret stuff</mytag> /// <param name="s">Description for s</param> static void Foo(string s) { Console.WriteLine(s); } static void Main() { Foo("42"); } }XML Documentation Files
<?xml version="1.0"?> <doc> <assembly> <name>DocTest</name> </assembly> <members> <member name="M:MyClass.Foo(System.String)"> <summary> The Foo method is called from <see cref="M:MyClass.Main">Main</see> </summary> <mytag>Secret stuff</mytag> <param name="s">Description for s</param> </member> </members> </doc>Predefined XML Tags <summary>, <remarks>
<summary>description</summary> <remarks>description</remarks><param>
<param name="name">description</param><returns>
<returns>description</returns><exception>
<exception [cref="type"]>description</exception><permission>
<permission [cref="type"]>description </permission>The C# compiler supports the following XML tags.<example>, <c>, <code>
<example>description</example> <c>code</c> <code>code</code><see>, <seealso>
<see cref="member">text</see> <seealso cref="member">text</seealso><value>
<value>description</value><paramref>
<paramref name="name"/><list>, <para>
Type or Member Cross-References<list type=[ bullet | number | table ]> <listheader> <term>name</term> <description>description</description> </listheader> <item> <term>name</term> <description>description</description> </item> </list> <para>text</para>
// Namespaces do not have independent signatures namespace NS { // T:NS.MyClass class MyClass { // F:NS.MyClass.aField string aField; // P:NS.MyClass.aProperty short aProperty {get {...} set {...}} // T:NS.MyClass.NestedType class NestedType {...}; // M:NS.MyClass.X() void X() {...} // M:NS.MyClass.Y(System.Int32,System.Double@,System.Decimal@) void Y(int p1, ref double p2, out decimal p3) {...} // M:NS.MyClass.Z(System.Char[],System.Single[0:,0:]) void Z(char[] p1, float[,] p2) {...} // M:NS.MyClass.op_Addition(NS.MyClass,NS.MyClass) public static MyClass operator+(MyClass c1, MyClass c2) {...} // M:NS.MyClass.op_Implicit(NS.MyClass)~System.Int32 public static implicit operator int(MyClass c) {...} // M:NS.MyClass.#ctor MyClass() {...} // M:NS.MyClass.Finalize ~MyClass() {...} // M:NS.MyClass.#cctor static MyClass() {...} } }
Programming the .NET Framework
Common Types
Object Classpublic class Object { public Object() {...} public virtual bool Equals(object o) {...} public virtual int GetHashCode(){...} public Type GetType(){...} public virtual string ToString() {...} protected virtual void Finalize() {...} protected object MemberwiseClone() {...} } using System; class Beeblebrox {} class Test { static void Main() { string s = "Zaphod"; Beeblebrox b = new Beeblebrox(); Console.WriteLine(s); // Prints "Zaphod" Console.WriteLine(b); // Prints "Beeblebrox" } }Creating BCL-Friendly Types
public class Point3D { public int x, y, z; public Point3D(int x, int y, int z) { this.x=x; this.y=y; this.z=z; // Initialize data } public override bool Equals(object o) { if (!(o is Point3D)) // Check for type equivalence return false; return (this==(Point3D)o); // Implemented by operator== } public static bool operator !=(Point3D lhs, Point3D rhs) { return (!(lhs==rhs)); // Implemented by operator== } public static bool operator ==(Point3D lhs, Point3D rhs) { return ((rhs.x==lhs.x) && (rhs.y==lhs.y) && (rhs.z==lhs.z)); } public override int GetHashCode(){ return x^y^z; } public override string ToString() { return String.Format("[{0},{1},{2}]", x, y, z); } } using System; using System.Collections; public class Point3D {...} class TestPoint3D { static void Main() { // Uses ToString, prints "p1=[1,1,1] p2=[2,2,2] p3=[2,2,2]" Point3D p1 = new Point3D(1,1,1); Point3D p2 = new Point3D(2,2,2); Point3D p3 = new Point3D(2,2,2); Console.WriteLine("p1={0} p2={1} p3={2}", p1, p2, p3); // Tests for equality to demonstrate Equals, == & != int i = 100; Console.WriteLine(p1.Equals(i)); // Prints "False" Console.WriteLine(p1==p2); // Prints "False" Console.WriteLine(p2==p3); // Prints "True" // Use a hashtable to store points (uses GetHashCode) Hashtable ht = new Hashtable(); ht["p1"] = p1; ht["p2"] = p2; ht["p3"] = p3; // Prints "p2=[2,2,2] p3=[2,2,2] p1=[1,1,1]" foreach (DictionaryEntry de in ht) Console.Write("{0}={1} ", de.Key, de.Value); } }ICloneable Interface
public interface ICloneable { object Clone(); } public class A : ICloneable { int x; public object Clone() { return MemberwiseClone(); } }IComparable Interface
interface IComparable { int CompareTo(object o); } using System; using System.Collections; class MyType : IComparable { public int x; public MyType(int x) { this.x = x; } public int CompareTo(object o) { return x -((MyType)o).x; } } class Test { static void Main() { ArrayList a = new ArrayList(); a.Add(new MyType(42)); a.Add(new MyType(17)); a.Sort(); foreach(MyType t in a) Console.WriteLine(((MyType)t).x); } }IFormattable Interface
public interface IFormattable { string Format(string format, IServiceObjectProvider sop); }
Math
Language Support for Mathstruct Vector { float direction; float magnitude; public Vector(float direction, float magnitude) { this.direction = direction; this.magnitude = magnitude; } public static Vector operator *(Vector v, float scale) { return new Vector(v.direction, v.magnitude * scale); } public static Vector operator /(Vector v, float scale) { return new Vector(v.direction, v.magnitude * scale); } ... } class Test { static void Main() { Vector [,] matrix = {{new Vector(1f,2f), new Vector(6f,2f)}, {new Vector(7f,3f), new Vector(4f,9f)}}; for (int i=0; i<matrix.GetLength(0); i++) for (int j=0; j<matrix.GetLength(1); j++) matrix[i, j] *= 2f; }Special Types and Operators
Math Class
using System; class Test { static void Main() { double a = 3; double b = 4; double C = Math.PI / 2; double c = Math.Sqrt (a*a+b*b-2*a*b*Math.Cos(C)); Console.WriteLine("The length of side c is "+c); } }Random Class
Random r = new Random(); Console.WriteLine(r.Next(50)); // return between 0 and 50
Strings
Immutability of Stringsstring a = "Heat"; string b = a.Insert(3, "r"); Console.WriteLine(b); // Prints Heart If you need a mutable string, see the StringBuilder class.String Interning
string a = "hello"; string b = "hello"; Console.WriteLine(a == b); // True Console.WriteLine(a.Equals(b)); // True Console.WriteLine((object)a == (object)b); // True!!Formatting Strings
using System; class TestFormatting { static void Main() { int i = 2; decimal m = 42.73m; string s = String.Format("Account {0} has {1:C}.", i, m); Console.WriteLine(s); // Prints "Account 2 has $42.73" } }Indexing Strings
using System; class TestIndexing { static void Main() { string s = "Going down?"; for (int i=0; i<s.Length; i++) Console.WriteLine(s[i]); // Prints s vertically } }Encoding Strings
using System; using System.Text; class TestEncoding { static void Main() { byte[] ba = new byte[] { 67, 35, 32, 105, 115, 32, 67, 79, 79, 76, 33 }; string s = Encoding.ASCII.GetString(ba); Console.WriteLine(s); } }StringBuilder Class
using System; using System.Text; class TestStringBuilder { static void Main() { StringBuilder sb = new StringBuilder("Hello, "); sb.Append("World"); sb[11] = '!'; Console.WriteLine(sb); // Hello, World! } }
Collections
ArrayList ClassArrayList a = new ArrayList(); a.Add("Vernon"); a.Add("Corey"); a.Add("William"); a.Add("Muzz"); a.Sort(); for(int i = 0; i < a.Count; i++) Console.WriteLine(a [i]);BitArray Class
BitArray bits = new BitArray(); bits.Length = 2; bits[1] = true; bits.Xor(bits); // Xor the array with itselfHashtable Class
Hashtable ht = new Hashtable(); ht["One"] = 1; ht["Two"] = 2; ht["Three"] = 3; Console.WriteLine(ht["Two"]); // Prints "2"Queue Class
Queue q = new Queue(); q.Enqueue(1); q.Enqueue(2); Console.WriteLine(q.Dequeue()); // Prints "1" Console.WriteLine(q.Dequeue()); // Prints "2"SortedList Class
SortedList s = new SortedList(); s["Zebra"] = 1; s["Antelope"] = 2; s["Eland"] = 3; s["Giraffe"] = 4; s["Meerkat"] = 5; s["Dassie"] = 6; s["Tokoloshe"] = 7; Console.WriteLine(s["Meerkat"]); // Prints "5" in 3 lookupsStack Class
Stack s = new Stack(); s.Push(1); // Stack = 1 s.Push(2); // Stack = 1,2 s.Push(3); // Stack = 1,2,3 Console.WriteLine(s.Pop()); // Prints 3, Stack=1,2 Console.WriteLine(s.Pop()); // Prints 2, Stack=1 Console.WriteLine(s.Pop()); // Prints 1, Stack=StringCollection Class
StringCollection sc = new StringCollection(); sc.Add("s1"); string[] sarr = {"s2", "s3", "s4"}; sc.AddRange(sarr); foreach (string s in sc) Console.Write("{0} ", s); // s1 s2 s3 s4Collection Interfaces
IEnumerable public interface IEnumerable { IEnumerator GetEnumerator(); }IEnumerator
public interface IEnumerator { bool MoveNext(); object Current {get;} void Reset(); } using System.Collections; public class MyCollection : IEnumerable { // ... public virtual IEnumerator GetEnumerator () { return new MyCollection.Enumerator(this); } private class Enumerator : IEnumerator { private MyCollection collection; private int currentIndex = -1; internal Enumerator (MyCollection collection) { this.collection = collection; } public object Current { get { if (currentIndex == collection.Count) throw new InvalidOperationException(); return collection [currentIndex]; } } public bool MoveNext () { if (currentIndex > collection.Count) throw new InvalidOperationException(); return ++currentIndex < collection.Count; } public void Reset () { currentIndex = -1; } } } MyCollection mcoll = new MyCollection(); ... // Using foreach: substitute your typename for XXX foreach (XXX item in mcoll) { Console.WriteLine(item); ... } // Using IEnumerator: substitute your typename for XXX IEnumerator ie = myc.GetEnumerator(); while (myc.MoveNext()) { XXX item = (XXX)myc.Current; Console.WriteLine(item); ... }ICollection Interface
public interface ICollection : IEnumerable { void CopyTo(Array array, int index); int Count {get;} bool IsReadOnly {get;} bool IsSynchronized {get;} object SyncRoot {get;} } IComparer Interface public interface IComparer { int Compare(object x, object y); }IList Interface
public interface IList : ICollection, IEnumerable { object this [int index] {get; set} int Add(object o); void Clear(); bool Contains(object value); int IndexOf(object value); void Insert(int index, object value); void Remove(object value); void RemoveAt(int index); }IDictionary Interface
public interface IDictionary : ICollection, IEnumerable { object this [object key] {get; set}; ICollection Keys {get;} ICollection Values {get;} void Clear(); bool Contains(object value); IDictionaryEnumerator GetEnumerator(); void Remove(object key); }IDictionaryEnumerator Interface
public interface IDictionaryEnumerator : IEnumerator { DictionaryEntry Entry {get;} object Key {get;} object Value {get;} }IHashCodeProvider Interface
public interface IHashCodeProvider { int GetHashCode(object o); }
Regular Expressions
Using Regular Expressions
// RegEx.cs - compile with /r:System.Text.RegularExpressions.dll using System; using System.Text.RegularExpressions; class TestRegEx { static void Main() { string pat = @"(?<1>[^\+!?#]*)(?<2>\+)?[^!?#]*?(?<3>#)?(?<4>[!?]?!|\?)?(?<3>#)?"; string t = "e8=Q+#!!"; Regex regex = new Regex(pat); Match m = regex.Match(t); if(m == null) System.Console.WriteLine("No Match"); else System.Console.Write( "Group 1 = "+ m.Group(1).ToString() + "\n" + "Group 2 = "+ m.Group(2).ToString() + "\n" + "Group 3 = "+ m.Group(3).ToString() + "\n" + "Group 4 = "+ m.Group(4).ToString() + "\n"); } } Group 1 = e8=Q Group 2 = + Group 3 = # Group 4 = !!
Input/Output
Concrete Stream-Derived Classesusing System.IO; class Test { static void Main() { Stream s = new FileStream("foo.txt", Filemode.Create); s.WriteByte("67"); s.WriteByte("35"); s.Close(); } }StreamReader and StreamWriter Classes
using System.Text; using System.IO; class Test { static void Main() { Stream fs = new FileStream ("foo.txt", FileMode.Create); StreamWriter sw = new StreamWriter(fs, Encoding.ASCII); sw.Write("Hello!"); sw.Close(); } }StringReader and StringWriter Classes
using System; using System.IO; using System.Text; class Test { static void Main() { StringBuilder sb = new StringBuilder(); StringWriter sw = new StringWriter(sb); WriteHello(sw); Console.WriteLine(sb); } static void WriteHello(TextWriter tw) { tw.Write("Hello, String I/O!"); } }Directories and Files
using System; using System.IO; class Test { static void Main(string[] args) { Stream s = File.OpenRead(args[0]); StreamReader sr = new StreamReader(s); Console.WriteLine(sr.ReadLine()); sr.Close(); } }
Networking
Generic Request/Response Architecture// Snarf.cs - compile with /r:System.Net.dll // Run Snarf.exe <http-uri> to retrieve a web page using System; using System.IO; using System.Net; using System.Text; class Snarf { static void Main(string[] args) { // Retrieve the data at the URL with an WebRequest ABC WebRequest req = WebRequestFactory.Create(args[0]); WebResponse resp = req.GetResponse(); // Read in the data, performing ASCII->Unicode encoding Stream s = resp.GetResponseStream(); StreamReader sr = new StreamReader(s, Encoding.ASCII); string doc = sr.ReadToEnd(); Console.WriteLine(doc); // Print result to console } }HTTP-Specific Support
// ProbeSvr.cs - compile with /r:System.Net.dll // Run ProbeSvr.exe <servername> to retrieve the server type using System; using System.Net; class ProbeSvr { static void Main(string[] args) { // Get instance of WebRequest ABC, convert to HttpWebRequest WebRequest req = WebRequestFactory.Create(args[0]); HttpWebRequest httpReq = (HttpWebRequest)req; // Access HTTP-specific features such as User-Agent httpReq.UserAgent = "CSPRProbe/1.0"; // Retrieve response and print to console WebResponse resp = req.GetResponse(); HttpWebResponse httpResp = (HttpWebResponse)resp; Console.WriteLine(httpResp.Server); } } // QOTDListener.cs - compile with /r:System.Net.dll // Run QOTDListener.exe to service incoming QOTD requests using System; using System.Net; using System.Net.Sockets; using System.Text; class QOTDListener { static string[] quotes = {@"Sufficiently advanced magic is indistinguishable from technology -- Terry Pratchett", @"Sufficiently advanced technology is indistinguishable from magic -- Arthur C Clarke" }; static void Main() { // Start a TCP listener on port 17 TCPListener l = new TCPListener(17); l.Start(); Console.WriteLine("Waiting for clients to connect"); Console.WriteLine("Press Ctrl+C to quit..."); int numServed = 1; while (true) { // Block waiting for an incoming socket connect request Socket s = l.Accept(); // Encode alternating quotes as bytes for sending Char[] carr = quotes[numServed%2].ToCharArray(); Byte[] barr = Encoding.ASCII.GetBytes(carr); // Return data to client, then clean up socket & repeat s.Send(barr, barr.Length, 0); s.Shutdown(SocketShutdown.SdBoth); s.Close(); Console.WriteLine("{0} quotes served...", numServed++); } } }Using DNS
// DNSLookup.cs - compile with /r:System.Net.dll // Run DNSLookup.exe <servername> to determine IP addresses using System; using System.Net; class DNSLookup { static void Main(string[] args) { IPHostEntry he = DNS.GetHostByName(args[0]); IPAddress[] addrs = he.AddressList; foreach (IPAddress addr in addrs) Console.WriteLine(addr); } }
Threading
using System; using System.Threading; class ThreadTest { static void Main() { Thread t = new Thread(new ThreadStart(Go)); t.Start(); Go(); } static void Go() { for (char c='a'; c<='z'; c++ ) Console.Write(c); } } abcdabcdefghijklmnopqrsefghjiklmnopqrstuvwxyztuvwxyzThread Synchronization
The Lock Statement
using System; using System.Threading; class LockTest { static void Main() { LockTest lt = new LockTest (); Thread t = new Thread(new ThreadStart(lt.Go)); t.Start(); lt.Go(); } void Go() { lock(this) for ( char c='a'; c<='z'; c++) Console.Write(c); } } abcdefghijklmnopqrstuvwzyzabcdefghijklmnopqrstuvwzyz System.Threading.Monitor.Enter(expression); try { ... } finally { System.Threading.Monitor.Exit(expression); }Pulse and Wait
using System; using System.Threading; class MonitorTest { static void Main() { MonitorTest mt = new MonitorTest(); Thread t = new Thread(new ThreadStart(mt.Go)); t.Start(); mt.Go(); } void Go() { for ( char c='a'; c<='z'; c++) lock(this) { Console.Write(c); Monitor.Pulse(this); Monitor.Wait(this); } } } aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzzDeadlocks
void Go() { for ( char c='a'; c<='z'; c++) lock(this) { Console.Write(c); Monitor.Pulse(this); if (c<'z') Monitor.Wait(this); } }
Reflection
Retrieving a Type DirectlyType t = Type.GetType("System.Int32"); Type t = typeof(System.Int32);Reflecting Over a Type Hierarchy
using System; using System.Reflection; class Test { static void Main() { object o = new Object(); DumpTypeInfo(o.GetType()); DumpTypeInfo(typeof(int)); DumpTypeInfo(Type.GetType("System.String")); } static void DumpTypeInfo(Type t) { Console.WriteLine("Type: {0}", t); // Retrieve the list of members in the type MemberInfo[] miarr = t.GetMembers(BindingFlags.LookupAll); // Print out details on each of them foreach (MemberInfo mi in miarr) Console.WriteLine(" {0}={1}", mi.MemberType.Format(), mi); } }Late Binding to Types
// Greeting.cs - compile with /t:library public abstract class Greeting { public abstract void SayHello(); } // English.cs - compile with /t:library /r:Greeting.dll using System; public class AmericanGreeting : Greeting { private string msg = "Hey, dude. Wassup!"; public override void SayHello() { Console.WriteLine(msg); } } public class BritishGreeting : Greeting { private string msg = "Good morning, old chap!"; public override void SayHello() { Console.WriteLine(msg); } } // SayHello.cs - compile with /r:Greeting.dll // Run with SayHello.exe <dllname1> <dllname2> ... <dllnameN> using System; using System.Reflection; class Test { static void Main (string[] args) { // Iterate over the cmd-line options, // trying to load each assembly foreach (string s in args) { Assembly a = Assembly.LoadFrom(s); // Pick through all the public type, looking for // subtypes of the abstract base class Greeting foreach (Type t in a.GetTypes()) if (t.IsSubclassOf(typeof(Greeting))) { // Having found an appropriate subtype, create it object o = Activator.CreateInstance(t); // Retrieve the SayHello MethodInfo & invoke it MethodInfo mi = t.GetMethod("SayHello"); mi.Invoke(o, null); } } } } Hey, dude. Wassup! Good morning, old chap!Forms of Activation
object o = Activator.CreateInstance("Assem1.dll", "Friendly.Greeting");Advanced Uses of Reflection
// InControl.cs - compile with /r:Greeting.dll,English.dll using System; using System.Reflection; class TestReflection { // Note: This method requires the ReflectionPermission perm. static void ModifyPrivateData(object o, string msg) { // Get a FieldInfo type for the private data member Type t = o.GetType(); FieldInfo fi = t.GetField("msg", BindingFlags.NonPublic| BindingFlags.Instance); // Use the FieldInfo to adjust the data member value fi.SetValue(o, msg); } static void Main() { // Create instances of both types BritishGreeting bg = new BritishGreeting(); AmericanGreeting ag = new AmericanGreeting(); // Adjust the private data via reflection ModifyPrivateData(ag, "Things are not the way they seem"); ModifyPrivateData(bg, "The runtime is in total control!"); // Display the modified greeting strings ag.SayHello(); // "Things are not the way they seem" bg.SayHello(); // "The runtime is in total control!" } } Things are not the way they seem The runtime is in total control!Creating New Types at Runtime
using System; using System.Reflection; using System.Reflection.Emit; public class Test { static void Main() { // Create a dynamic assembly in the current AppDomain AppDomain ad = AppDomain.CurrentDomain; AssemblyName an = new AssemblyName(); an.Name = "DynAssembly"; AssemblyBuilder ab = ad.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run); // Create a module in the assembly & a type in the module Assembly a = (Assembly)ab; ModuleBuilder modb = a.DefineDynamicModule("DynModule"); TypeBuilder tb = modb.DefineType("AgentSmith", TypeAttributes.Public); // Add a SayHello member to the type MethodBuilder mb = tb.DefineMethod("SayHello", MethodAttributes.Public, null, null); // Generate the MSIL for the SayHello Member ILGenerator ilg = mb.GetILGenerator(); ilg.EmitWriteLine("Never send a human to do a machine's job."); ilg.Emit(OpCodes.Ret); // Finalize the type so we can create it tb.CreateType(); // Create an instance of the new type Type t = Type.GetType("AgentSmith"); object o = Activator.CreateInstance(t); // Prints "Never send a human to do a machine's job." t.GetMethod("SayHello").Invoke(o, null); } }
Custom Attributes
Defining a New Custom Attributeusing System; [AttributeUsage(AttributeTargets.ClassMembers, AllowMultiple=true)] class CrossRefAttribute : Attribute { Type xref; string desc = ""; public string Description { set { desc=value; } } public CrossRefAttribute(Type xref) { this.xref=xref; } public override string ToString() { string tmp = (desc.Length>0) ? " ("+desc+")" : ""; return "CrossRef to "+xref.ToString()+tmp; } } [CrossRef(typeof(Bar), Description="Foos often hang around Bars")] class Foo {...}Retrieving a Custom Attribute at Runtime
using System; [Serializable, Obsolete] class Test { static void Main() { Type t = typeof(Test); object[] caarr = t.GetCustomAttributes(); Console.WriteLine("{0} has {1} custom attribute(s)", t, caarr.Length); foreach (object ca in caarr) Console.WriteLine(ca); } } Test has 1 custom attribute(s) System.ObsoleteAttributeDispose and Close Methods
public class Worker { ... public void Dispose() { // Perform normal cleanup ... // Mark this object finalized GC.SuppressFinalize(this); } protected override void Finalize() { Dispose(); base.Finalize(); } }
Interop With Native DLLs
int MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCation, UINT uType); using System.Runtime.InteropServices; [DllImport("user32.dll")] static extern int MessageBox(int hWnd, string text, string caption, int type);Marshaling Common Types
using System.Runtime.InteropServices; static extern int Foo([MarshalAs(UnmanagedType.LPStr)] string s); using System.Runtime.InteropServices; [DllImport("kernel32.dll")] static extern int GetWindowsDirectory(StringBuilder sb, int maxChars); class Test { static void Main() { StringBuilder s = new String(256); GetWindowsDirectory(s, 256); Console.WriteLine(s); } }Marshalling Classes and Structs
using System.Runtime.InteropServices; [StructLayout(LayoutKind.Sequential)] class SystemTime { public ushort wYear; public ushort wMonth; public ushort wDayOfWeek; public ushort wDay; public ushort wHour; public ushort wMinute; public ushort wSecond; public ushort wMilliseconds; } class Test { [DllImport("kernel32.dll")] static extern void GetSystemTime(SystemTime t); static void Main() { SystemTime t = new SystemTime(); GetSystemTime(t); Console.WriteLine(t.wYear); } }In and Out Marshaling
struct SystemTime {...} static extern void GetSystemTime(ref SystemTime t); static extern void Foo([in] int[] array);Callbacks from Unmanaged Code
class Test { delegate bool CallBack(int hWnd, int lParam); [DllImport("user32.dll")] static extern int EnumWindows(CallBack hWnd, int lParam); static bool PrintWindow(int hWnd, int lParam) { Console.WriteLine(hWnd); return true; } static void Main() { CallBack e = new CallBack(PrintWindow); EnumWindows(e, 0); } }
Interop With COM
Exposing COM Objects To C#// IMAdd.cs - compile with /r:Messenger.dll // Run IMAdd.exe <UserID> to add an MSN Instant // Messenger user to Contacts // Run TlbImp.exe "C:\Program Files\Messenger\msmsgs.exe" // to create Messenger.dll using System.Runtime.InteropServices; using Messenger; // COM API for MSN Instant Messenger class COMConsumer { static void Main(string[] args) { MessengerApp m = new MessengerApp() m.LaunchAddContactUI(args[0]); } }Exposing C# Objects To COM
[GuidAttribute("aa6b10a2-dc4f-4a24-ae5e-90362c2142c1")] public interface : IRunInfo { [DispId(1)] string GetRunInfo(); } [GuidAttribute("b72ccf55-88cc-4657-8577-72bd0ff767bc")] public class StackSnapshot : IRunInfo { public StackSnapshot() { st = new StackTrace(); } [DispId(1)] public string GetRunInfo() { return st.ToString(); } private StackTrace st; }
Regular Expressions
using System; class TestDefaultFormats { static void Main() { int i = 654321; Console.WriteLine("{0:C}", i); // $654,321.00 Console.WriteLine("{0:D}", i); // 654321 Console.WriteLine("{0:E}", i); // 6.543210E+005 Console.WriteLine("{0:F}", i); // 654321.00 Console.WriteLine("{0:G}", i); // 654321 Console.WriteLine("{0:N}", i); // 654,321.00 Console.WriteLine("{0:X}", i); // 9FBF1 Console.WriteLine("{0:x}", i); // 9fbf1 } } using System; class TestIntegerFormats { static void Main() { int i = 123; Console.WriteLine("{0:C6}", i); // $123.000000 Console.WriteLine("{0:D6}", i); // 000123 Console.WriteLine("{0:E6}", i); // 1.230000E+002 Console.WriteLine("{0:G6}", i); // 123 Console.WriteLine("{0:N6}", i); // 123.000000 Console.WriteLine("{0:X6}", i); // 00007B i = -123; Console.WriteLine("{0:C6}", i); // ($123.000000) Console.WriteLine("{0:D6}", i); // -000123 Console.WriteLine("{0:E6}", i); // -1.230000E+002 Console.WriteLine("{0:G6}", i); // -123 Console.WriteLine("{0:N6}", i); // -123.000000 Console.WriteLine("{0:X6}", i); // FFFF85 i = 0; Console.WriteLine("{0:C6}", i); // $0.000000 Console.WriteLine("{0:D6}", i); // 000000 Console.WriteLine("{0:E6}", i); // 0.000000E+000 Console.WriteLine("{0:G6}", i); // 0 Console.WriteLine("{0:N6}", i); // 0.000000 Console.WriteLine("{0:X6}", i); // 000000 } } using System; class TestDoubleFormats { static void Main() { double d = 1.23; Console.WriteLine("{0:C6}", d); // $1.230000 Console.WriteLine("{0:E6}", d); // 1.230000E+000 Console.WriteLine("{0:G6}", d); // 1.23 Console.WriteLine("{0:N6}", d); // 1.230000 d = -1.23; Console.WriteLine("{0:C6}", d); // ($1.230000) Console.WriteLine("{0:E6}", d); // -1.230000E+000 Console.WriteLine("{0:G6}", d); // -1.23 Console.WriteLine("{0:N6}", d); // -1.230000 d = 0; Console.WriteLine("{0:C6}", d); // $0.000000 Console.WriteLine("{0:E6}", d); // 0.000000E+000 Console.WriteLine("{0:G6}", d); // 0 Console.WriteLine("{0:N6}", d); // 0.000000 } } using System; class TestIntegerCustomFormats { static void Main() { int i = 123; Console.WriteLine("{0:#0}", i); // 123 Console.WriteLine("{0:#0;(#0)}", i); // 123 Console.WriteLine("{0:#0;(#0);<zero>}", i); // 123 Console.WriteLine("{0:#%}", i); // 12300% i = -123; Console.WriteLine("{0:#0}", i); // -123 Console.WriteLine("{0:#0;(#0)}", i); // (123) Console.WriteLine("{0:#0;(#0);<zero>}", i); // (123) Console.WriteLine("{0:#%}", i); // -12300% i = 0; Console.WriteLine("{0:#0}", i); // 0 Console.WriteLine("{0:#0;(#0)}", i); // 0 Console.WriteLine("{0:#0;(#0);<zero>}", i); // <zero> Console.WriteLine("{0:#%}", i); // % } } using System; class TestDoubleCustomFormats { static void Main() { double d = 1.23; Console.WriteLine("{0:#.000E+00}", d); // 1.230E+00 Console.WriteLine( "{0:#.000E+00;(#.000E+00)}", d); // 1.230E+00 Console.WriteLine( "{0:#.000E+00;(#.000E+00);<zero>}", d); // 1.230E+00 Console.WriteLine("{0:#%}", d); // 123% d = -1.23; Console.WriteLine("{0:#.000E+00}", d); // -1.230E+00 Console.WriteLine( "{0:#.000E+00;(#.000E+00)}", d); // (1.230E+00) Console.WriteLine( "{0:#.000E+00;(#.000E+00);<zero>}", d); // (1.230E+00) Console.WriteLine("{0:#%}", d); // -123% d = 0; Console.WriteLine("{0:#.000E+00}", d); // 0.000E-01 Console.WriteLine( "{0:#.000E+00;(#.000E+00)}", d); // 0.000E-01 Console.WriteLine( "{0:#.000E+00;(#.000E+00);<zero>}", d); // <zero> Console.WriteLine("{0:#%}", d); // % } }
DateTime Format Specifiers
using System; class TestDateTimeFormats { static void Main() { DateTime dt = new DateTime(2000, 10, 11, 15, 32, 14); // Prints "2000-10-11T15:32:14" Console.WriteLine(dt.ToString()); // Prints "Wednesday, October 11, 2000" Console.WriteLine("{0}", dt); // Prints "10/11/2000" Console.WriteLine("{0:d}", dt); // Prints "Wednesday, October 11, 2000" Console.WriteLine("{0:D}", dt); // Prints "Wednesday, October 11, 2000 3:32 PM" Console.WriteLine("{0:f}", dt); // Prints "Wednesday, October 11, 2000 3:32:14 PM" Console.WriteLine("{0:F}", dt); // Prints "10/11/2000 3:32 PM" Console.WriteLine("{0:g}", dt); // Prints "10/11/2000 3:32:14 PM" Console.WriteLine("{0:G}", dt); // Prints "October 11" Console.WriteLine("{0:m}", dt); // Prints "October 11" Console.WriteLine("{0:M}", dt); // Prints "Wed, 11 Oct 2000 22:32:14 GMT" Console.WriteLine("{0:r}", dt); // Prints "Wed, 11 Oct 2000 22:32:14 GMT" Console.WriteLine("{0:R}", dt); // Prints "3:32 PM" Console.WriteLine("{0:t}", dt); // Prints "3:32:14 PM" Console.WriteLine("{0:T}", dt); // Prints "2000-10-11 22:32:14Z" Console.WriteLine("{0:u}", dt); // Prints "Wednesday, October 11, 2000 10:32:14 PM" Console.WriteLine("{0:U}", dt); // Prints "October, 2000" Console.WriteLine("{0:y}", dt); // Prints "October, 2000" Console.WriteLine("{0:Y}", dt); // Prints "Wednesday the 11 day of October in the year 2000" Console.WriteLine( "{0:dddd 'the' d 'day of' MMMM 'in the year' yyyy}", dt); } }
Using nmake
REF=/r:c.dll DEBUG=/debug .SUFFIXES: .exe .dll .cs .cs.dll: csc /t:module $*.cs .cs.exe: csc $(DEBUG) $(REF) @<<big.tmp $*.cs $(SRCLIST) << all : d.exe f.exe d.exe : d.cs c.dll c.dll : a.dll b.dll al /out:c.dll a.dll b.dll b.dll : b.cs a.dll : a.cs key.snk : sn -k $*.snk e.dll : a.dll b.dll key.snk al /out:$*.dll /keyfile:key.snk a.dll b.dll al /i:$*.dll f.exe : f.cs e.dll csc $(DEBUG) /r:.\e.dll f.cs clean: del a.dll b.dll c.dll d.exe /q