Sie sind auf Seite 1von 32

Dotnet Concepts:Difference Between ref and out keywords:Ref and Out Parameters: Both the parameters passed by reference,

while for the Ref Parameter you need to initialize it before passing to the function and out parameter you do not need to initialize before passing to function. You need to assign values into these parameter before returning to the function. Ref (initialize the variable) int getal = 0; Fun_RefTest(ref getal);

Out (no need to initialize the variable) int getal; Fun_OutTest(out getal);

The out and the ref parameters are used to return values in the same variables, that you pass an an argument of a method. These both parameters are very useful when your method needs to return more than one values. In this article, I will explain how do you use these parameters in your C# applications. The out Parameter The out parameter can be used to return the values in the same variable passed as a parameter of the method. Any changes made to the parameter will be reflected in the variable. public class mathClass { public static int TestOut(out int iVal1, out int iVal2) { iVal1 = 10; iVal2 = 20; return 0; } public static void Main() { int i, j; // variable need not be initialized Console.WriteLine(TestOut(out i, out j)); Console.WriteLine(i); Console.WriteLine(j); } } The ref parameter

The ref keyword on a method parameter causes a method to refer to the same variable that was passed as an input parameter for the same method. If you do any changes to the variable, they will be reflected in the variable. You can even use ref for more than one method parameters. namespace TestRefP { using System; public class myClass { public static void RefTest(ref int iVal1 ) { iVal1 += 2; } public static void Main() { int i; // variable need to be initialized i = 3; RefTest(ref i ); Console.WriteLine(i); } } } Difference between delete, drop and truncate:DELETE: - Removes some or all rows from a table. - A WHERE clause can be used to only remove some rows. If no WHERE condition is specified, all rows will be removed. - Causes all DELETE triggers on the table to fire. - It deallocated records row-by-row in transaction logs and thus is slower than TRUNCATE. - According to MS BOL, if a table is a heap or no clustered index is defined than the row-pages emptied are not deallocated and remain allocated in the heap. Thus no other object can reuse this associated space. Thus to deallocate the space a Clustered index is required or TABLOCK hint should be applied in the DELETE statement. - Thus it requires more locks and database resources. - This is a DML command as it is just used to manipulate/modify the table data. It does not change the property of a table. TRUNCATE: - Removes all rows from a table. - Does not require a WHERE clause, not allowed here. - Identity columns are re-seeded on this operation, if no seed was defined then the default value 1 is used. - No triggers are fired on this operation because it does not log individual rows. - It deallocates data pages instead of rows in transaction logs, thus is faster than DELETE. - Thus it also requires less number of locks. - TRUNCATE is not possible when a table is reference by a Foreign Key or tables used in replication or with Indexed views.

- This is a DDL command as its resets identity columns, deallocates data pages and empties them for use of other objects in the database. Note: It is a misconception among some people that TRUNCATE cannot be rolled back. But in reality TRUNCATE operation can be ROLLED BACKED. Thus DELETE & TRUNCATE both can be rollbacked if provided inside a transaction. The only method to rollback a committed transaction after DELETE/TRUNCATE is to restore the last backup and run transactions logs till the time when DELETE/TRUNCATE is about to happen. DROP: The DROP TABLE command removes one or more table(s) from the database. - All related data, indexes, triggers, constraints, and permission specifications for those tables are dropped by them operation. - Some objects like Views, Stored Procedures that references the dropped table are not dropped and must be explicitly dropped. - Cannot drop a table that is referenced by any Foreign Key constraint. - According to MS BOL, Large tables and indexes that use more than 128 extents are dropped in two separate phases: logical and physical. In the logical phase, the existing allocation units used by the table are marked for deallocation and locked until the transaction commits. In the physical phase, the IAM pages marked for deallocation are physically dropped in batches. Abstract Classes:There may be a situation where it is not possible to define a method in base class and every derived class must override that method. In this situation abstract methods are used. When a method is declared as abstract in the base class then it is not possible to define it in the derived class and every derived class of that class must provide its own definition for that method. When a class contains at least one abstract method, then the class mus t be declared as abstract class. It is mandatory to override abstract method in the derived class. When a class is declared as abstract class, then it is not possible to create an instance for that class. But it can be used as a parameter in a method. Example The following example creates three classes shape, circle and rectangle where circle and rectangle are inherited from the class shape and overrides the methods Area() and Circumference() that are declared as abstract in Shape class and as Shape cl ass contains abstract methods it is declared as abstract class.

using System; namespace ProgramCall { //Abstract class

abstract class Shape1 { protected float R, L, B; //Abstract methods can have only declarations public abstract float Area(); public abstract float Circumference(); }

class Rectangle1 : Shape1 { public void GetLB() { Console.Write("Enter Length : "); L = float.Parse(Console.ReadLine()); Console.Write("Enter Breadth : "); B = float.Parse(Console.ReadLine()); }

public override float Area() { return L * B; } public override float Circumference() { return 2 * (L + B); } }

class Circle1 : Shape1 { public void GetRadius() { Console.Write("Enter Radius : "); R = float.Parse(Console.ReadLine()); } public override float Area() {

return 3.14F * R * R; } public override float Circumference() { return 2 * 3.14F * R; } } class MainClass { public static void Calculate(Shape1 S) { Console.WriteLine("Area : {0}", S.Area()); Console.WriteLine("Circumference : {0}", S.Circumference()); } static void Main() { Rectangle1 R = new Rectangle1(); R.GetLB(); Calculate(R); Console.WriteLine(); Circle1 C = new Circle1(); C.GetRadius(); Calculate(C); Console.Read(); } } } Output

Enter Length : 10 Enter Breadth : 12 Area : 120 Circumference : 44 Enter Radius : 5 Area : 78.5 Circumference : 31.4 Note

In the above example method calculate takes a parameter of type Shape1 from which rectangle1 and circle1 classes are inherited. A base class type parameter can t ake derived class object as an argument. Hence the calculate method can take either rectangle1 or circle1 object as argument and the actual argument in the parameter S will be determined only at runtime and hence this example is an example for runtime poly morphism. Partial Classes:It is possible to split the definition of a class or a struct, an interface or a method over two or more source files. Each source file contains a section of the type or method definition, and all parts are combined when the application is compiled. Partial Classes

There are several situations when splitting a class definition is desirable:


When working on large projects, spreading a class over separate files enables multiple programmers to work on it at the same time. When working with automatically generated source, code can be added to the class without having to recreate the source file. Visual Studio uses this approach when it creates Windows Forms, Web service wrapper code, and so on. You can create code that uses these classes without having to modify the file created by Visual Studio. To split a class definition, use the partial keyword modifier, as shown here:

C# public partial class Employee { public void DoWork() { } } public partial class Employee { public void GoToLunch() { } } The partial keyword indicates that other parts of the class, struct, or interface can be defined in the namespace. All the parts must use the partial keyword. All the parts must be available at compile time to form the final type. All the parts must have the same accessibility, such as public, private, and so on. If any part is declared abstract, then the whole type is considered abstract. If any part is declared sealed, then the whole type is considered sealed. If any part declares a base type, then the whole type inherits that class.

All the parts that specify a base class must agree, but parts that omit a base class still inherit the base type. Parts can specify different base interfaces, and the final type implements all the interfaces listed by all the partial declarations. Any class, struct, or interface members declared in a partial definition are available to all the other parts. The final type is the combination of all the parts at compile time. Note The partial modifier is not available on delegate or enumeration declarations. The following example shows that nested types can be partial, even if the type they are nested within is not partial itself. C# class Container { partial class Nested { void Test() { } } partial class Nested { void Test2() { } } } At compile time, attributes of partial-type definitions are merged. For example, consider the following declarations: C# [SerializableAttribute] partial class Moon { } [ObsoleteAttribute] partial class Moon { } They are equivalent to the following declarations: C# [SerializableAttribute] [ObsoleteAttribute] class Moon { } The following are merged from all the partial-type definitions:

XML comments interfaces generic-type parameter attributes class attributes members

For example, consider the following declarations: C# partial class Earth : Planet, IRotate { } partial class Earth : IRevolve { } They are equivalent to the following declarations: C# class Earth : Planet, IRotate, IRevolve { } Restrictions

There are several rules to follow when you are working with partial class definitions:

All partial-type definitions meant to be parts of the same type must be modified with partial. For example, the following class declarations generate an error: C# public partial class A { } //public class tcA { } // Error, must also be marked partial

The partial modifier can only appear immediately before the keywords class, struct, or interface. Nested partial types are allowed in partial-type definitions as illustrated in the following example: C# partial class ClassWithNestedClass { partial class NestedClass { } } partial class ClassWithNestedClass { partial class NestedClass { } }

All partial-type definitions meant to be parts of the same type must be defined in the same assembly and the same module (.exe or .dll file). Partial definitions cannot span multiple modules. The class name and generic-type parameters must match on all partial-type definitions. Generic types can be partial. Each partial declaration must use the same parameter names in the same order. The following keywords on a partial-type definition are optional, but if present on one partialtype definition, cannot conflict with the keywords specified on another partial definition for the same type: public

private protected internal abstract sealed base class new modifier (nested parts) generic constraints

Partial Methods:A partial class or struct may contain a partial method. One part of the class contains the signature of the method. An optional implementation may be defined in the same part or another part. If the implementation is not supplied, then the method and all calls to the method are removed at compile time. Partial methods enable the implementer of one part of a class to define a method, similar to an event. The implementer of the other part of the class can decide whether to implement the method or not. If the method is not implemented, then the compiler removes the method signature and all calls to the method. The calls to the method, including any results that would occur from evaluation of arguments in the calls, have no effect at run time. Therefore, any code in the partial class can freely use a partial method, even if the implementation is not supplied. No compile-time or run-time errors will result if the method is called but not implemented. Partial methods are especially useful as a way to customize generated code. They allow for a method name and signature to be reserved, so that generated code can call the method but the developer can decide whether to implement the method. Much like partial classes, partial methods enable code created by a code generator and code created by a human developer to work together without run-time costs. A partial method declaration consists of two parts: the definition, and the implementation. These may be in separate parts of a partial class, or in the same part. If there is no implementation declaration, then the compiler optimizes away both the defining declaration and all calls to the method. // Definition in file1.cs partial void onNameChanged(); // Implementation in file2.cs partial void onNameChanged() { // method body }

Partial method declarations must begin with the contextual keyword partial and the method must return void. Partial methods can have ref but not out parameters. Partial methods are implicitly private, and therefore they cannot be virtual. Partial methods cannot be extern, because the presence of the body determines whether they are defining or implementing. Partial methods can have static and unsafe modifiers.

Partial methods can be generic. Constraints are put on the defining partial method declaration, and may optionally be repeated on the implementing one. Parameter and type parameter names do not have to be the same in the implementing declaration as in the defining one. You can make a delegate to a partial method that has been defined and implemented, but not to a partial method that has only been defined.

Collections:There are two distinct collection types in C#. The standard collections, which are found under the System.Collections namespace and the generic collections, under System.Collections.Generic. The generic collections are more flexible and are the preferred way to work with data. The generic collections or generics were introduced in .NET framework 2.0. Generics enhance code reuse, type safety, and performance. ArrayList ArrayList is a collection from a standard System.Collections namespace. It is a dynamic array. It provides random access to its elements. An ArrayList automatically expands as data is added. Unlike arrays, an ArrayList can hold data of multiple data types. Elements in the ArrayList are accessed via an integer index. Indexes are zero based. Indexing of elements and insertion and deletion at the end of the ArrayList takes constant time. Inserting or deleting an element in the middle of the dynamic array is more costly. It takes linear time.

using System; using System.Collections; public class CSharpApp { class Empty {} static void Main() { ArrayList da = new ArrayList(); da.Add("Visual Basic"); da.Add(344); da.Add(55); da.Add(new Empty()); da.Remove(55); foreach(object el in da) { Console.WriteLine(el); } }

In the above example, we have created an ArrayList collection. We have added some elements to it. They are of various data type, string, int and a class object. using System.Collections; In order to work with ArrayList collection, we need to import System.Collectionsnamespace. ArrayList da = new ArrayList(); An ArrayList collection is created. da.Add("Visual Basic"); da.Add(344); da.Add(55); da.Add(new Empty()); da.Remove(55); We add five elements to the array with the Add() method. da.Remove(55); We remove one element. foreach(object el in da) { Console.WriteLine(el); } We iterate through the array and print its elements to the console. $ ./arraylist.exe Visual Basic 344 CSharpApp+Empty Output. List A List is a strongly typed list of objects that can be accessed by index. It can be found under System.Collections.Generic namespace.

using System; using System.Collections.Generic;

public class CSharpApp { static void Main() { List<string> langs = new List<string>(); langs.Add("Java"); langs.Add("C#"); langs.Add("C"); langs.Add("C++"); langs.Add("Ruby"); langs.Add("Javascript"); Console.WriteLine(langs.Contains("C#")); Console.WriteLine(langs[1]); Console.WriteLine(langs[2]); langs.Remove("C#"); langs.Remove("C"); Console.WriteLine(langs.Contains("C#")); langs.Insert(4, "Haskell"); langs.Sort(); foreach(string lang in langs) { Console.WriteLine(lang); } } }

In the preceding example, we work with the List collection. using System.Collections.Generic; In order to work with the List collection, we need to import theSystem.Collections.Generic namespace. List<string> langs = new List<string>(); A generic dynamic array is created. We specify that we will work with strings with the type specified inside <> characters. langs.Add("Java");

langs.Add("C#"); langs.Add("C"); ... We add elements to the List using the Add() method. Console.WriteLine(langs.Contains("C#")); We check if the List contains a specific string using the Contains() method. Console.WriteLine(langs[1]); Console.WriteLine(langs[2]); We access the second and the third element of the List using the index notation. langs.Remove("C#"); langs.Remove("C"); We remove two strings from the List. langs.Insert(4, "Haskell"); We insert a string at a specific location. langs.Sort(); We sort the elements using the Sort() method. $ ./list.exe True C# C False C++ Haskell Java Javascript Ruby Outcome of the example. LinkedList LinkedList is a generic doubly linked list in C#. LinkedList only allows sequential access. LinkedList allows for constant-time insertions or removals, but only sequential access of elements. Because linked lists need extra storage for references, they are impractical for lists of small data items such as characters. Unlike dynamic arrays, arbitrary number of items can be added to the linked list (limited by the memory of course) without the need to realocate, which is an expensive operation.

using System; using System.Collections.Generic; public class CSharpApp { static void Main() { LinkedList<int> nums = new LinkedList<int>(); nums.AddLast(23); nums.AddLast(34); nums.AddLast(33); nums.AddLast(11); nums.AddLast(6); nums.AddFirst(9); nums.AddFirst(7); LinkedListNode<int> node = nums.Find(6); nums.AddBefore(node, 5); foreach(int num in nums) { Console.WriteLine(num); } } }

This is a LinkedList example with some of its methods. LinkedList<int> nums = new LinkedList<int>(); This is an integer LinkedList. nums.AddLast(23); ... nums.AddFirst(7); We populate the linked list using the AddLast() and AddFirst() methods. LinkedListNode<int> node = nums.Find(6); nums.AddBefore(node, 5); A LinkedList consists of nodes. We find a specific node and add an element before it. foreach(int num in nums) { Console.WriteLine(num); }

Printing all elements to the console. Dictionary A dictionary, also called an associative array, is a collection of unique keys and a collection of values, where each key is associated with one value. Retrieving and adding values is very fast. Dictionaries take more memory, because for each value there is also a key.

using System; using System.Collections.Generic;

public class CSharpApp { static void Main() { Dictionary<string, string> domains = new Dictionary<string, string>(); domains.Add("de", "Germany"); domains.Add("sk", "Slovakia"); domains.Add("us", "United States"); domains.Add("ru", "Russia"); domains.Add("hu", "Hungary"); domains.Add("pl", "Poland"); Console.WriteLine(domains["sk"]); Console.WriteLine(domains["de"]); Console.WriteLine("Dictionary has {0} items", domains.Count); Console.WriteLine("Keys of the dictionary:"); List<string> keys = new List<string>(domains.Keys); foreach(string key in keys) { Console.WriteLine("{0}", key); } Console.WriteLine("Values of the dictionary:"); List<string> vals = new List<string>(domains.Values); foreach(string val in vals) { Console.WriteLine("{0}", val); } Console.WriteLine("Keys and values of the dictionary:");

foreach(KeyValuePair<string, string> kvp in domains) { Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value); } } }

We have a dictionary, where we map domain names to their country names. Dictionary<string, string> domains = new Dictionary<string, string>(); We create a dictionary with string keys and values. domains.Add("de", "Germany"); domains.Add("sk", "Slovakia"); domains.Add("us", "United States"); ... We add some data to the dictionary. The first string is the key. The second is the value. Console.WriteLine(domains["sk"]); Console.WriteLine(domains["de"]); Here we retrieve two values by their keys. Console.WriteLine("Dictionary has {0} items", domains.Count); We print the number of items by referring to the Count property. List<string> keys = new List<string>(domains.Keys); foreach(string key in keys) { Console.WriteLine("{0}", key); } These lines retrieve all keys from the dictionary. List<string> vals = new List<string>(domains.Values); foreach(string val in vals) { Console.WriteLine("{0}", val); }

These lines retrieve all values from the dictionary. foreach(KeyValuePair<string, string> kvp in domains) { Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value); } Finally, we print both keys and values of the dictionary. $ ./dictionary.exe Slovakia Germany Dictionary has 6 items Keys of the dictionary: de sk us ru hu pl Values of the dictionary: Germany Slovakia United States Russia Hungary Poland Keys and values of the dictionary: Key = de, Value = Germany Key = sk, Value = Slovakia Key = us, Value = United States Key = ru, Value = Russia Key = hu, Value = Hungary Key = pl, Value = Poland This is the output of the example. Queues A queue is a First-In-First-Out (FIFO) data structure. The first element added to the queue will be the first one to be removed. Queues may be used to process messages as they appear or serve customers as they come. The first customer which comes should be served first.

using System; using System.Collections.Generic;

public class CSharpApp {

static void Main() { Queue<string> msgs = new Queue<string>(); msgs.Enqueue("Message 1"); msgs.Enqueue("Message 2"); msgs.Enqueue("Message 3"); msgs.Enqueue("Message 4"); msgs.Enqueue("Message 5"); Console.WriteLine(msgs.Dequeue()); Console.WriteLine(msgs.Peek()); Console.WriteLine(msgs.Peek()); Console.WriteLine(); foreach(string msg in msgs) { Console.WriteLine(msg); } } }

In our example, we have a queue with messages. Queue<string> msgs = new Queue<string>(); A queue of strings is created. msgs.Enqueue("Message 1"); msgs.Enqueue("Message 2"); ... The Enqueue() adds a message to the end of the queue. Console.WriteLine(msgs.Dequeue()); The Dequeue() method removes and returns the item at the beginning of the queue. Console.WriteLine(msgs.Peek()); The Peek() method returns the next item from the queue, but does not remove it from the collection. $ ./queue.exe Message 1 Message 2 Message 2

Message 2 Message 3 Message 4 Message 5 The Dequeue() method removes the "Message 1" from the collection. The Peek()method does not. The "Message 2" remains in the collection. Stacks A stack is a Last-In-First-Out (LIFO) data structure. The last element added to the queue will be the first one to be removed. The C language uses a stack to store local data in a function. The stack is also used when implementing calculators.

using System; using System.Collections.Generic;

public class CSharpApp { static void Main() { Stack<int> stc = new Stack<int>(); stc.Push(1); stc.Push(4); stc.Push(3); stc.Push(6); stc.Push(4); Console.WriteLine(stc.Pop()); Console.WriteLine(stc.Peek()); Console.WriteLine(stc.Peek()); Console.WriteLine(); foreach(int item in stc) { Console.WriteLine(item); } } }

We have a simple stack example above. Stack<int> stc = new Stack<int>(); A Stack data structure is created.

stc.Push(1); stc.Push(4); ... The Push() method adds an item at the top of the stack. Console.WriteLine(stc.Pop()); The Pop() method removes and returns the item from the top of the stack. Console.WriteLine(stc.Peek()); The Peek() method returns the item from the top of the stack. It does not remove it. $ ./stack.exe 4 6 6 6 3 4 1 Output.

Delegates and Events:A delegate is a C# language element that allows you to reference a method. If you were a C or C++ programmer, this would sound familiar because a delegate is basically a function pointer. However, developers who have used other languages are probably wondering, "Why do I need a reference to a method? The answer boils down to giving you maximum flexibility to implement any functionality you want at runtime. Think about how you use methods right now. You write an algorithm that does its thing by manipulating the values of variables and calling methods directly by name. What if you wanted an algorithm that was very flexible, reusable, and allowed you to implement different functionality as the need arises? Furthermore, let's say that this was an algorithm that supported some type of data structure that you wanted to have sorted, but you also want to enable this data structure to hold different types. If you don't know what the types are, how could you decide an appropriate comparison routine? Perhaps you could implement an if/then/else or switch statement to handle well-known types, but this would still be limiting and require overhead to determine the type. Another alternative would be for all the types to implement an interface that declared a common method your algorithm would call, which is actually a nice solution. However, since this lesson is about delegates, we'll apply a delegate solution, which is quite elegant. You could solve this problem by passing a delegate to your algorithm and letting the contained method, which the delegate refers to, perform the comparison operation. Such an operation is performed in Listing 14-1.

Listing 14-1. Declaring and Implementing a Delegate: SimpleDelegate.cs using System; // this is the delegate declaration public delegate int Comparer(object obj1, object obj2); public class Name { public string FirstName = null; public string LastName = null; public Name(string first, string last) { FirstName = first; LastName = last; } // this is the delegate method handler public static int CompareFirstNames(object name1, object name2) { string n1 = ((Name)name1).FirstName; string n2 = ((Name)name2).FirstName; if (String.Compare(n1, n2) > 0) { return 1; } else if (String.Compare(n1, n2) < 0) { return -1; } else { return 0; } } public override string ToString() { return FirstName + " " + LastName; } } class SimpleDelegate { Name[] names = new Name[5]; public SimpleDelegate() { names[0] = new Name("Joe", "Mayo");

names[1] = new Name("John", "Hancock"); names[2] = new Name("Jane", "Doe"); names[3] = new Name("John", "Doe"); names[4] = new Name("Jack", "Smith"); } static void Main(string[] args) { SimpleDelegate sd = new SimpleDelegate(); // this is the delegate instantiation Comparer cmp = new Comparer(Name.CompareFirstNames); Console.WriteLine("\nBefore Sort: \n"); sd.PrintNames(); // observe the delegate argument sd.Sort(cmp); Console.WriteLine("\nAfter Sort: \n"); sd.PrintNames(); } // observe the delegate parameter public void Sort(Comparer compare) { object temp; for (int i=0; i < names.Length; i++) { for (int j=i; j < names.Length; j++) { // using delegate "compare" just like // a normal method if ( compare(names[i], names[j]) > 0 ) { temp = names[i]; names[i] = names[j]; names[j] = (Name)temp; } } } } public void PrintNames() { Console.WriteLine("Names: \n"); foreach (Name name in names)

{ Console.WriteLine(name.ToString()); } } } The first thing the program in Listing 14-1 does is declare a delegate. Delegate declarations look somewhat like methods, except they have thedelegate modifier, are terminated with a semi-colon (;), and have no implementation. Below, is the delegate declaration from Listing 14-1. public delegate int Comparer(object obj1, object obj2); This delegate declaration defines the signature of a delegate handler method that this delegate can refer to. The delegate handler method, for the Comparer delegate, can have any name, but must have a first parameter of type object, a second parameter of type object, and return anint type. The following method from Listing 14-1 shows a delegate handler method that conforms to the signature of the Comparer delegate. public static int CompareFirstNames(object name1, object name2) { ... } Note: The CompareFirstNames method calls String.Compare to compare the FirstName properties of the two Name instances. The String class has many convenience methods, such as Compare, for working with strings. Please don't allow the implementation of this method to interfere with learning how delegates work. What you should concentrate on is that CompareFirstNames is a handler method that a delegate can refer to, regardless of the code inside of that method. To use a delegate, you must create an instance of it. The instance is created, similar to a class instance, with a single parameter identifying the appropriate delegate handler method, as shown below. Comparer cmp = new Comparer(Name.CompareFirstNames); The delegate, cmp, is then used as a parameter to the Sort() method, which uses it just like a normal method. Observe the way the delegate is passed to the Sort() method as a parameter in the code below. sd.Sort(cmp); Using this technique, any delegate handler method may be passed to the Sort() method at run-time. i.e. You could define a method handler named CompareLastNames(), instantiate a new Comparer delegate instance with it, and pass the new delegate to the Sort() method. Events Traditional Console applications operate by waiting for a user to press a key or type a command and press the Enter key. Then they perform some pre-defined operation and either quit or return to the original prompt that they started from. This works, but is inflexible in that everything is hard-wired and follows a rigid path of execution. In stark contrast, modern GUI programs operate on an event-

based model. That is, some event in the system occurs and interested modules are notified so they can react appropriately. With Windows Forms, there is not a polling mechanism taking up resources and you don't have to code a loop that sits waiting for input. It is all built into the system with events. A C# event is a class member that is activated whenever the event it was designed for occurs. I like to use the term "fires" when the event is activated. Anyone interested in the event can register and be notified as soon as the event fires. At the time an event fires, registered methods will be invoked. Events and delegates work hand-in-hand to provide a program's functionality. It starts with a class that declares an event. Any class, including the same class that the event is declared in, may register one of its methods for the event. This occurs through a delegate, which specifies the signature of the method that is registered for the event. The delegate may be one of the pre-defined .NET delegates or one you declare yourself. Whichever is appropriate, you assign the delegate to the event, which effectively registers the method that will be called when theevent fires. Listing 14-2 shows a couple different ways to implement events. Listing 14-2. Declaring and Implementing Events: Eventdemo.cs using System; using System.Drawing; using System.Windows.Forms; // custom delegate public delegate void Startdelegate(); class Eventdemo : Form { // custom event public event Startdelegate StartEvent; public Eventdemo() { Button clickMe = new Button(); clickMe.Parent = this; clickMe.Text = "Click Me"; clickMe.Location = new Point( (ClientSize.Width - clickMe.Width) /2, (ClientSize.Height - clickMe.Height)/2); // an EventHandler delegate is assigned // to the button's Click event clickMe.Click += new EventHandler(OnClickMeClicked); // our custom "Startdelegate" delegate is assigned // to our custom "StartEvent" event. StartEvent += new Startdelegate(OnStartEvent); // fire our custom event StartEvent();

} // this method is called when the "clickMe" button is pressed public void OnClickMeClicked(object sender, EventArgs ea) { MessageBox.Show("You Clicked My Button!"); } // this method is called when the "StartEvent" Event is fired public void OnStartEvent() { MessageBox.Show("I Just Started!"); } static void Main(string[] args) { Application.Run(new Eventdemo()); } } Note: If you're using Visual Studio or another IDE, remember to add references to System.Drawing.dll and System.Windows.Forms.dll before compiling Listing 14.2 or just add the code to a Windows Forms project. Teaching the operation of Visual Studio or other IDE's is out-ofscope for this tutorial. You may have noticed that Listing 14-2 is a Windows Forms program. Although I haven't covered Windows Forms in this tutorial, you should know enough about C# programming in general that you won't be lost. To help out, I'll give a brief explanation of some of the parts that you may not be familiar with. The Eventdemo class inherits Form, which essentially makes it a Windows Form. This automatically gives you all the functionality of a Windows Form, including Title Bar, Minimize/Maximize/Close buttons, System Menu, and Borders. A lot of power, that inheritance thing, eh? The way a Windows Form's application is started is by calling the Run() method of the static Application object with a reference to the formobject as its parameter. This starts up all the underlying Windows plumbing, displays the GUI, and ensures that events are fired as appropriate. Let's look at the custom event first. Below is the event declaration, which is a member of the Eventdemo class. It is declared with the eventkeyword, a delegate type, and an event name. public event Startdelegate StartEvent; Anyone interested in an event can register by hooking up a delegate for that event. On the next line, we have a delegate of type Startdelegate, which the event was declared to accept, hooked up to the StartEvent event. The += syntax registers a delegate with an event. To unregister with an event, use the -= with the same syntax. StartEvent += new Startdelegate(OnStartEvent);

Firing an event looks just like a method call, as shown below: StartEvent(); This was how to implement events from scratch, declaring the event and delegate yourself. However, much of the event programming you'll do will be with pre-defined events and delegates. This leads us to the other event code you see in Listing 14-2, where we hook up anEventHandler delegate to a Button Click event. clickMe.Click += new EventHandler(OnClickMeClicked); The Click event already belongs to the Button class and all we have to do is reference it when registering a delegate. Similarly, theEventHandler delegate already exists in the System namespace of the .NET Frameworks Class Library. All you really need to do is define your callback method (delegate handler method) that is invoked when someone presses the clickMe button. The OnClickMeClicked() method, shown below, conforms to the signature of the EventHandler delegate, which you can look up in the .NET Framework Class Library reference. public void OnClickMeClicked(object sender, EventArgs ea) { MessageBox.Show("You Clicked My Button!"); } Any time the clickMe button is pressed with a mouse, it will fire the Click event, which will invoke the OnClickMeClicked() method. The Buttonclass takes care of firing the Click event and there's nothing more you have to do. Because it is so easy to use pre-defined events anddelegates, it would be a good idea to check if some exist already that will do what you need, before creating your own. LINQ:LINQ (Language Integrated Query) is a Microsoft programming model and methodology that essentially adds formal query capabilities into Microsoft .NET-based programming languages. LINQ offers a compact, expressive, and intelligible syntax for manipulating data. The real value of LINQ comes from its ability to apply the same query to an SQL database, a DataSet, an array of objects in memory and to many other types of data as well. LINQ requires the presence of specific language extensions. LINQ uses an SQL-like syntax to make query expressions well beyond the capabilities of embedded SQL as implemented in programming languages. That's because embedded SQL uses a simplified, streamlined syntax to add SQL statements to other programming languages, where there's no attempt to integrate such statements into the native syntax and typing mechanisms. Thus, you can't invoke native language structures such as functions in embedded SQL statements, as you can using LINQ, because it is implemented to use native syntax, structures, and typing mechanisms. Furthermore, LINQ may be used to access all kinds of data, whereas embedded SQL is limited to addressing only databases that can handle SQL queries. DLL HELL:In windows applications some dlls are shared ones. Suppose app1 is an application running perfectly. It is sharing a shared dll named shared1.dll. You are installing another application app2. Suppose app2 application is also having a shared dll named shared1.dll. At the time of app2 installation,

installer will overwrite the shared1.dll which is already there on our system and being shared by app1. The new shared1.dll may be different than the previous dll which is overwritten. Now the application app1 which is depending on overwritten shared1.dll will become defunct. app1 will fail. that's all about dll hell. Dot net shared assemblies are strongly named. Different assemblies with same name but with different version numbers may coexist in shared folders. This is the solution provided by dot net. Cursors:In computer science and technology, a database cursor is a control structure that enables traversal over the records in a database. Cursors facilitate subsequent processing in conjunction with the traversal, such as retrieval, addition and removal of database records. The database cursor characteristic of traversal makes cursors akin to the programming language concept of iterator. Cursors are used by database programmers to process individual rows returned by database system queries. Cursors enable manipulation of whole result sets at oncea capability that most procedural programming languages lack. In this scenario, a cursor enables the rows in a result-set to be processed sequentially. In SQL procedures, a cursor makes it possible to define a result set (a set of data rows) and perform complex logic on a row by row basis. By using the same mechanics, an SQL procedure can also define a result set and return it directly to the caller of the SQL procedure or to a client application. A cursor can be viewed as a pointer to one row in a set of rows. The cursor can only reference one row at a time, but can move to other rows of the result set as needed. To use cursors in SQL procedures, you need to do the following: 1. 2. 3. 4. Declare a cursor that defines a result set. Open the cursor to establish the result set. Fetch the data into local variables as needed from the cursor, one row at a time. Close the cursor when done.

A programmer makes a cursor known to the DBMS by using a DECLARE ... CURSOR statement and assigning the cursor a (compulsory) name: DECLARE cursor_name CURSOR FOR SELECT ... FROM ... Before code can access the data, it must open the cursor with the OPEN statement. Directly following a successful opening, the cursor is positioned before the first row in the result set. OPEN cursor_name Programs position cursors on a specific row in the result set with the FETCH statement. A fetch operation transfers the data of the row into the application. FETCH cursor_name INTO ...

Once an application has processed all available rows or the fetch operation is to be positioned on a non-existing row (compare scrollable cursors below), the DBMS returns a SQLSTATE '02000' (usually accompanied by an SQLCODE +100) to indicate the end of the result set. The final step involves closing the cursor using the CLOSE statement: CLOSE cursor_name After closing a cursor, a program can open it again, which implies that the DBMS re-evaluates the same query or a different query and builds a new result-set. Virtual Functions:In object-oriented programming, a virtual function or virtual method is a function or method whose behavior can be overridden within an inheriting class by a function with the same signature. This concept is a very important part of the polymorphism portion of object-oriented programming (OOP). In C#, a base class must provide the virtual modifier for any virtual method, and derived classes must provide the override modifier for any overridden method inherited from a base class. The following is an example in C#.NET using System; using System.Collections.Generic; namespace ConsoleApplication1 { public class Animal { public virtual void Eat() { Console.WriteLine("I eat like a generic Animal."); } } public class Wolf : Animal { public override void Eat() { Console.WriteLine("I eat like a wolf!"); } } public class Fish : Animal { public override void Eat() { Console.WriteLine("I eat like a fish!"); } } public class GoldFish : Fish

{ public override void Eat() { Console.WriteLine("I eat like a goldfish!"); } } public class OtherAnimal : Animal { // Eat() method is not overridden, so the base class method will be used. } public class Program { public static void Main(string[] args) { IList<Animal> animals = new List<Animal>(); animals.Add(new Animal()); animals.Add(new Wolf()); animals.Add(new Fish()); animals.Add(new GoldFish()); animals.Add(new OtherAnimal()); foreach (Animal currentAnimal in animals) { currentAnimal.Eat(); } } } } Output: I eat like a generic Animal. I eat like a wolf! I eat like a fish! I eat like a goldfish! I eat like a generic Animal. A pure virtual function or pure virtual method is a virtual function that is required to be implemented by a derived class, if that class is not abstract. Classes containing pure virtual methods are termed "abstract"; they cannot be instantiated directly. A subclass of an abstract class can only be instantiated directly if all inherited pure virtual methods have been implemented by that class or a parent class. Pure virtual methods typically have a declaration (signature) and no definition (implementation). As an example, an abstract base class MathSymbol may provide a pure virtual function doOperation(), and derived classes Plus and Minus implement doOperation() to provide concrete implementations. Implementing doOperation() would not make sense in the MathSymbol class, as MathSymbol is an abstract concept whose behaviour is defined solely for

each given kind (subclass) of MathSymbol. Similarly, a given subclass of MathSymbol would not be complete without an implementation of doOperation(). Although pure virtual methods typically have no implementation in the class that declares them, pure virtual methods in C++ are permitted to contain an implementation in their declaring class, providing fallback or default behaviour that a derived class can delegate to, if appropriate. Pure virtual functions can also be used where the method declarations are being used to define an interface - similar to what the interface keyword in Java explicitly specifies. In such a use, derived classes will supply all implementations. In such a design pattern, the abstract class which serves as an interface will contains only pure virtual functions, but no data members or ordinary methods. In C++, using such purely abstract classes as interfaces works because C++ supports multiple inheritance. However, because many OO languages do not support multiple inheritance, they often provide a separate interface mechanism. An example is the Java programming language. C# and Java In C# and Java, pure virtual methods are declared using the abstract keyword. Such a method cannot have a body. A class containing abstract methods (either directly, or inherited and not overridden) must itself be declared abstract. (But the converse is not true - an abstract class is not required to have any abstract methods.) An abstract class cannot be instantiated. Any concrete (instantiable) class with an abstract class as its ancestor must implement all unimplemented abstract methods in order to successfully compile. abstract class B { abstract void a_pure_virtual_function(); } C# and Java also use interfaces. All of the methods declared in an interface are implicitly abstract: interface C { void a_pure_virtual_function(); } Anonymous Methods:An anonymous method is a method without a name - which is why it is called anonymous. You don't declare anonymous methods like regular methods. Instead they get hooked up directly to events. You'll see a code example shortly. To see the benefit of anonymous methods, you need to look at how they improve your development experience over using delegates. Think about all of the moving pieces there are with using delegates: you declare the delegate, write a method with a signature defined by the delegate interface, declare the event based on that delegate, and then write code to hook the handler method up to the delegate. With all this work to do, no wonder programmers, who are new to C# delegates, have to do a double-take to understand how they work. Because you can hook an anonymous method up to an event directly, a couple of the steps of working with delegates can be removed. The next section shows you how this works.

Implementing an Anonymous Method An anonymous method uses the keyword, delegate, instead of a method name. This is followed by the body of the method. Typical usage of an anonymous method is to assign it to an event. Listing 21-1 shows how this works. Listing 21-1. Implementing an Anonymous Method using System.Windows.Forms; public partial class Form1 : Form { public Form1() { Button btnHello = new Button(); btnHello.Text = "Hello"; btnHello.Click += delegate { MessageBox.Show("Hello"); }; Controls.Add(btnHello); } } The code in Listing 21-1 is a Windows Forms application. It instantiates a Button control and sets its Text to "Hello". Notice the combine, +=, syntax being used to hook up the anonymous method. You can tell that it is an anonymous method because it uses the delegate keyword, followed by the method body in curly braces. Essentially, you have defined a method inside of a method, but the body of the anonymous method doesn't execute with the rest of the code. Because you hook it up to the event, the anonymous method doesn't execute until the Click event is raised. When you run the program and click the Hello button, you'll see a message box that say's "Hello" - courtesy of the anonymous method. Using Controls.Add, adds the new button control to the window. Otherwise the window wouldn't know anything about the Button and you wouldn't see the button when the program runs. Using Delegate Parameters with Anonymous Methods Many event handlers need to use the parameters of the delegate they are based on. The previous example didn't use those parameters, so it was more convenient to not declare them, which C# allows. Listing 21-2 shows you how to use parameters if you need to. Listing 21-2. Using Parameters with Anonymous Methods using System; using System.Windows.Forms; public partial class Form1 : Form {

public Form1() { Button btnHello = new Button(); btnHello.Text = "Hello"; btnHello.Click += delegate { MessageBox.Show("Hello"); }; Button btnGoodBye = new Button(); btnGoodBye.Text = "Goodbye"; btnGoodBye.Left = btnHello.Width + 5; btnGoodBye.Click += delegate(object sender, EventArgs e) { string message = (sender as Button).Text; MessageBox.Show(message); }; Controls.Add(btnHello); Controls.Add(btnGoodBye); } } The bold parts of Listing 21-2 show another Button control added to the code from Listing 21-1. Besides changing the text, btnGoodBye is moved to the right of btnHello by setting it's Left property to 5 pixels beyond the right edge of btnHello. If we didn't do this, btnGoodBye would cover btnHello because both of their Top and Left properties would default to 0. Beyond implementation details, the real code for you to pay attention to is the implementation of the anonymous method. Notice that thedelegate keyword now has a parameter list. this parameter list must match the delegate type of the event that the anonymous method is being hooked up to. The delegate type of the Click event is EventHandler, which has the following signature: public delegate void EventHandler(object sender, EventArgs e); Notice the EventHandler parameters. Now, here's how the Button control's Click event is defined: public event EventHandler Click; Notice that the delegate type of the Click event is EventHandler. This is why the anonymous method, assigned to btnGoodBye.Click in Listing 21-2, must have the same parameters as the EventHandler delegate. Multithreading in ASP.net:http://www.devx.com/dotnet/Article/7003

Das könnte Ihnen auch gefallen