Programming with C#
[Conditional("Debug")] // method will only be available in Debug version void DoSomeDump(){...}
// not necessary: includes to use library functions/classes using System; using System.Windows.Forms; namespace MyConsole // all items "should" be within a namespace { class MyClass { // entry point, each function "must" be a member of a class or struct static int Main (string[] in_commandLineArgs) { Console.WriteLine ("Hello, World!"); MessageBox.Show("Hello, World!"); return 0; } } }
class MyClass : MyBaseClass { // Constructor MyClass (int in_num) : base (in_num) // executes the base class constructor {...} // Constructor MyClass (double in_num) : this () // executes the 0 param MyClass constructor {...} // Default constructor (replaces compiler generated version) // "private" prevents instantiation from outside private MyClass(){...} // static constructor static MyClass() { // init static fields } // Any method public int DoSomething() { return 17; } // operator overloads always are static methods public static MyClass operator + (MyClass lhs, MyClass rhs) { MyClass ret = new MyClass(); ret.m_strField = lhs.m_strField + rhs.m_strField; ret.m_intField = lhs.m_intField + rhs.m_intField; return ret; } // regular fields with direct initialization private string m_strField = "Initial value"; private int m_intField = 36; // static fields with initialization private static double s_doubleField = 3.14; // constant // set at compile time, cannot be changed within constructor, // is implicitly static public const int PI = 3.14; // readonly constant // initialized once at runtime within a static constructor public static readonly int EPSILON; }
// within class, implementation of Dispose: public void Dispose() { Dispose(true); // inform Garbage Collector that a call of the destructor // is no longer necessary and the freeing of managed memory // need not be delayed to long GC.SuppressFinalize(this); } protected virtual void Dispose (bool disposing) { if (disposing) { // cleanup of managed resources } // cleanup of unmanaged resources } ~Destructor() { // cleanup resources }Der Aufruf von Dispose() kann auch automatisch ausgeführt werden
using (MyClass myObject = new MyClass()) { // use myObejct here } // myObejct.Dispose() will be called automatically here
MyBaseClass myBaseObject; myBaseObject = new MyDerivedClass(); // each class derives from .NET library class System.Object, which // is represented as "object" within C# syntax object myObject = new MyClass();Überschreiben virtueller und nicht virtueller Methoden:
class MyBaseClass { public virtual void DoSomethingVirtual(int in_num) {...} public void DoSomethingNonVirtual(int in_num) {...} // a derived class can only be instantiated if all abstract // methdods have been implemented public abstract void DoAnythingElse(); } // Override a virtual and a non virtual function class MyDerivedClass : MyBaseClass { public override void DoSomethingVirtual(int in_num) {...} public new void DoSomethingNonVirtual(int in_num) {...} }
// cast can be defined as implicit or explicit public static implicit operator MyDest (MySource in_source) { ... // return MyDest instance }Anwendung:
MySource source = new MySource(); // if cast operator was defined "implicit" MyDest dest = source; // if cast operator was defined "explicit" MyDest dest = (MyDest) source;Reaktion bei Fehlschlag der cast-Operation von Basisklasse auf abgeleitete Klasse:
// throws an exception MyDerivedClass derived = (MyDerivedClass) baseRef; // use null instead of exception MyDerivedClass derived as (MyDerivedClass) baseRef; // derived now has value "null"
interface IMyInterface { void DoSomething (int in_num); } // not allowed: access modifiers, implementation code, virtual, abstract // deriving from other interface is possibleImplementierung von Interfaces inerhalb einer Klasse:
class MyClass : MyBaseClass, IMyInterface, IMyInterface2 { // implement interface method // here we choose to define it as "public virtual" public virtual void DoSomething (int in_num){...} }Prüfung, auf Vorhandensein eines Interfaces zur Laufzeit
IMyInterface myInterface; myInterface = someObject as IMyInterface; if (myInterface != null) { // interface exists and can be used }
if (myInt)
in C# zwingend: if (myInt != 0)
switch (myString) { case "SomeText": // do something break; case "AnotherText"; // do something goto case "NextCase"; // no implicit fall through allowed, // if case is non empty case "NextCase": // implicit fall through is allowed // for empty case case "LastCase": // do something break; default: // do something break; }
foreach (int number in myNumberArray) { Console.WriteLine (number); // access to elements is READONLY }Zum Verändern der Elemente ist eine herkömmliche for-Schleife erforderlich:
for (int i = 0; i< myNumberArray.Length; i++) { myNumberArray[i] += 3; // change element }
double d = double.Parse("3.14")
)
string myFilePath = @"C:\MyFolder\MySubFolder"; // double "\\" is not required string multiLineMessage = @"Line 1 Line2 Line3"; // carriage returns are part of the defined string
reference type
MyClass var1; // uninitialized reference var1 = new MyClass(); // new calls default constructor // initializes fields, // and allocates memory on the heap var1.SomeIntField = 17; MyClass var2 = var1; // var2 now points to the same object as var1 var2.SomeIntField = 36; // also changes var1.SomeIntField var2 = null; // var2 does no longer refer to anything // var1 still refers to the objectvalue type
MyStruct myVar; // creates struct on the stack, // but does not call constructor, // fields are uninitialized myVar = new MyStruct(); // new executes default constructor, // initializes fields, // no effect on memory allocation, // already exists on stackBoxing: Bei Bedarf kann auch ein value type in einen reference type umgewandelt werden:
int i = 33; object boxedI = (object) i; // now use the reference e.g. by calling a method expecting a reference // somewhere else convert back to value type: int k = (int) boxedI; // may throw an exception
Lokale Variablen müssen explizit initialisiert werden:
int myInteger; // will contain random data myInteger = new int(); // now default constructor initializes with 0 // or simpler: int anotherInt = 0;
class MyClass { private int m_someInt; // define property "SomeInt" // Remark: Omitting set/get is possible and leads to // a read-only / write-only property public int SomeInt { get { return m_someInt; } // implicit input param is "value", return type is void set { m_someInt = value; } } }
// definition of method within MyClass public void ChangeNumbers (ref int io_numberOne, ref int io_numberTwo); ... // Calling method ChangeNumbers requires initialization // of ref params and again usage of attribute "ref" int numberOne = 12; int numberTwo = 400; myClass.ChangeNumbers (ref numberOne, ref numberTwo);
// definition of method within MyClass public void CalculateResult (int in_startValue, out int out_result); ... //Calling method CalculateResult does not // require initialization of out param, but again usage of attribute "out" int result; // not initialized myClass.CalculateResult (4711, out result);
// initialized with default constructor, here 0.0, // the size of the array belongs to the instance not to its type double [] myArray1 = new double[10]; double [] myArray2 = new double[50]; // explicit initialization double [] myArray3 = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9,0, 10.0}; // example for three dimensional rectangular array // number of elements is 2x3x2 = 12 int [,,] myArray3D; myArray3D = new int [2,3,2]; // example for two dimensional jagged array // number of elements can be specific for each row int [][] myJaggedArray = new int [3][]; for (int = 0; i<3; i++) myJaggedArray[i] = new int [2*i];
IndexOutOfBounds
Exception geworfen
System.Collections.ArrayList
möglich
// definition of enum enum Color {RED, GREEN, BLUE, YELLOW} // usage requires the enumeration name: Color myColor = Color.GREEN; // read value from string Color myColor = (Color) Enum.Parse (typeof(Color), "YELLOW", true);
try { // do something which may cause an exception // code may contain several calls of return: // before really returning the finally block is executed! return; } // optionally catch the exception to perform // some error handling catch (MyException e) // MyException must be derived from System.Exception { // error handling } // optionally perform some cleanup operations // block is also called without preceding catch block finally { // code is executed in any case before method returns // e.g. free resources allocated within try block }
public unsafe void SomeMethod(){...}
unsafe class SomeClass(){...}
unsafe {...}
MyClass myObject = new MyClass(); fixed (int *pInt = &myObject.m_someIntField) { // use pointer to m_someIntField; }
Definition eines Delegate:
delegate void MyDelegateFunction (int in_num);Beispielklasse, deren Methode über das Delegate aufgerufen werden soll:
class MyClass { void MyMethod (int in_maxNum){...}; }Beispielmethode, die einen Delegate als Parameter erwartet
void MethodAcceptingDelegate (MyDelegateFunction in_function) { // call the method with param 36 in_function(36); }Einsatz des Delegate:
MyClass myObject = new MyClass; MyDelegateFunction myFunc = new MyDelegateFunction (myObject.MyMethod) // simply call delegatefucntion myFunc(4711); // pass it to some other method MethodAcceptingDelegate(myFunc);Delegates können mehrere Methoden verkapseln (Verknüpfung mit +=), die dann nacheinander aufgerufen werden.
delegate void MyEventClass(obj sender, EventArgs e);
Deklaration eines Events innerhalb einer Klasse:
public event MyEventClass OnMyEvent;
Verknüpfung des Events mit einer Handlerroutine:
eventSourceObject.OnMyEvent += MyHandlerMethod;
Auslösen des Events in der EventSource-Klasse:
OnMyEvent(this, new EventArgs());
// Definition of custom EventData: // Notification data delivered together with the PerformanceDataEvent public class PerformanceDataEventArgs : EventArgs { private readonly double m_counterValue; ... // other data and accessor functions } // Delegate declaration // Clients may implement handler methods with this signature: // The current counter value is delivered public delegate void EventHandler_PerformanceData(object sender, PerformanceDataEventArgs e); // Event source // Class PerformanceTracker watches an arbitrary system performance counter // and emits events with the current counter values. class PerformanceTracker { //----- Event ----- // The current counter value is delivered public event EventHandler_PerformanceData Event_PerformanceData; //----- Internal helper method to create and send event ----- protected virtual void RaiseEvent_PerformanceData() { EventHandler_PerformanceData handler = Event_PerformanceData; if (handler != null) // there are really clients registered { // store performance data within specific EventArgs PerformanceDataEventArgs e = new PerformanceDataEventArgs( m_info, m_currentCounterValue); // Invokes the delegates, i.e. informs all registered clients handler(this, e); } } //----- Application code raising event via helper function ----- // Periodic timer handler method private void RetrievePerformanceData() { ... // get performance data and store in class atribute // Inform clients about new counter value RaiseEvent_PerformanceData(); } }
// Class which is interested on performance data // received from class PerformanceTracker class SomeClient { SomeClient() { m_performanceTracker = new PerformanceTracker(); // Connect with events from PerformanceTracker m_performanceTracker.Event_PerformanceData += this.NewPerformanceDataReceived; // Start tracking m_performanceTracker.StartTracking(m_perfCounterInfo); // From now on we will receive all performance data through // event handler routine NewPerformanceDataReceived } // Event handler routine to process performance data public void NewPerformanceDataReceived(object sender, PerformanceDataEventArgs e) { // display the received event data somewhere on the GUI lblCurrentCounterValue.Text = e.m_counterValue.ToString(); } }