Вы находитесь на странице: 1из 44

INTRODUCTION TO C#.

NET

INTRODUCTION TO THE C# LANGUAGE


C# Language

C# is an elegant and type-safe object-oriented language that enables developers to build a wide range of secure and robust applications that run on the .NET Framework. C# syntax simplifies many of the complexities of C++ while providing powerful features such as nullable value types, enumerations, delegates, anonymous methods and direct memory access, which are not found in Java. As an object-oriented language, C# supports the concepts of encapsulation, inheritance and polymorphism. All variables and methods, including the Main method, the application's entry point, are encapsulated within class definitions. A class may inherit directly from one parent class, but it may implement any number of interfaces. Methods that override virtual methods in a parent class require the override keyword as a way to avoid accidental redefinition. If we need to interact with other Windows software such as COM objects or native Win32 DLLs, we can do this in C# through a process called "Interop." Interop enables C# programs to do just about anything that a native C++ application can do. C# even supports pointers and the concept of "unsafe" code for those cases in which direct memory access is absolutely critical.

.NET FRAMEWORK PLATFORM ARCHITECTURE

.NET FRAMEWORK PLATFORM ARCHITECTURE

C# programs run on the .NET Framework, an integral component of Windows that includes a virtual execution system called the common language runtime (CLR) and a unified set of class libraries. The CLR is Microsoft's commercial implementation of the common language infrastructure (CLI), an international standard that is the basis for creating execution and development environments in which languages and libraries work together seamlessly. Source code written in C# is compiled into an intermediate language (IL) that conforms to the CLI specification. The IL code, along with resources such as bitmaps and strings, is stored on disk in an executable file called an assembly, typically with an extension of .exe or .dll. An assembly contains a manifest that provides information on the assembly's types, version, culture, and security requirements. When the C# program is executed, the assembly is loaded into the CLR, which might take various actions based on the information in the manifest. Then, if the security requirements are met, the CLR performs just in time (JIT) compilation to convert the IL code into native machine instructions. The CLR also provides other services related to automatic garbage collection, exception handling, and resource management. Code that is executed by the CLR is sometimes referred to as "managed code," in contrast to "unmanaged code" which is compiled into native machine language that targets a specific system.

CONTROL STATEMENTS

The foreach Loop A foreach loop is used to iterate through the items in a list. It operates on arrays or collections such as ArrayList can be found in the System.Collections namespace using System; class ForEachLoop { public static void Main() { string[] names = {"Cheryl", "Joe", "Matt", "Robert"}; foreach (string person in names) { Console.WriteLine("{0} ", person); } }

INTRODUCTION TO CLASS

Classes are declared by using the keyword class followed by the class name and a set of class members surrounded by curly braces. Every class has a constructor, which is called automatically any time an instance of a class is created. The purpose of constructors is to initialize class members when an instance of the class is created. Constructors do not have return values and always have the same name as the class.

INTRODUCTION TO CLASS

/ Namespace Declaration using System; // helper class class OutputClass { string myString; // Constructor public OutputClass(string inputString) { myString = inputString; } // Instance Method public void printString() { Console.WriteLine("{0}", myString); }

// Program start class class ExampleClass { // Main begins program execution. public static void Main() { // Instance of OutputClass OutputClass outCl = new OutputClass("This is printed by the output class."); // Call Output class' method outCl.printString();

PROPERTIES

Properties provide the opportunity to protect a field in a class by reading and writing to it through the property.

using System;
class Person { private string myName ="N/A"; // Declare a Name property of type string: public string Name

{
get { return myName; } set

{
myName = value; } }

PROPERTIES
C# 3.0 introduced a new syntax for a property, called an autoimplemented property, which allows us to create properties without get and set accessor implementations.
using System; public class Customer { public int ID { get; set; }

public string Name { get; set; }


} public class AutoImplementedCustomerManager { static void Main() { Customer cust = new Customer(); cust.ID = 1; cust.Name = "Amelio Rosales"; Console.WriteLine( "ID: {0}, Name: {1}", cust.ID, cust.Name); Console.ReadKey(); } }

INDEXERS

Defining an indexer allows us to create classes that act like "virtual arrays. Instances of that class can be accessed using the [] array access operator. Defining an indexer in C# is similar to defining operator [] in C++, but is considerably more flexible
using System; /// <summary> /// A simple indexer example. /// </summary> class IntIndexer { private string[] myData; public IntIndexer(int size) { myData = new string[size]; for (int i=0; i < size; i++) { myData[i] = "empty"; }

public string this[int pos] { get { return myData[pos]; } set { myData[pos] = value; } }

INDEXERS

static void Main(string[] args) { int size = 10;

IntIndexer myInd = new IntIndexer(size);


myInd[9] = "Some Value"; myInd[3] = "Another Value"; myInd[5] = "Any Value"; Console.WriteLine("\nIndexer Output\n"); for (int i=0; i < size; i++) { Console.WriteLine("myInd[{0}]: {1}", i, myInd[i]); } } }

STURCTS

A struct is a value type.

using System;

struct SimpleStruct
{ private int xval; public int X { get { return xval; } set { if (value < 100) xval = value; } }

STURCTS
public void DisplayX() { Console.WriteLine("The stored value is: {0}", xval); } } class TestClass { public static void Main() { SimpleStruct ss = new SimpleStruct(); ss.X = 5; ss.DisplayX(); } }

DIFFERENCE BETWEEN STRUCTS AND CLASSES


classes are reference types and structs are value types. When we call the New operator on a class, it will be allocated on the heap. However, when we instantiate a struct, it gets created on the stack when passing a struct to a method, it's passed by value instead of as a reference. Structs can declare constructors, but they must take parameters. It is an error to declare a default (parameterless) constructor for a struct. Struct members cannot have initializers. A default constructor is always provided to initialize the struct members to their default values. There is no inheritance for structs as there is for classes. A struct cannot inherit from another struct or class, and it cannot be the base of a class. Structs, however, inherit from the base class object. A struct can implement interfaces, and it does that exactly as classes do.

DIFFERENCE BETWEEN STRUCTS AND CLASSES


interface IImage { void Paint(); } struct Picture : IImage { public void Paint() { // painting code goes here } private int x, y, z; // other struct members }

INTERFACE

An interface looks like a class, but has no implementation. The only thing it contains are declarations of events, indexers, methods and/or properties. Interfaces must be implemented by derived classes and structs, they define a contract. For instance, if class foo implements theIDisposable interface, it is making a statement that it guarantees it has the Dispose() method, which is the only member of the Idisposableinterface.

INTERFACE
using System;
interface IParentInterface { void ParentInterfaceMethod(); } interface IMyInterface : IParentInterface { void MethodToImplement(); } class InterfaceImplementer : IMyInterface { static void Main() { InterfaceImplementer iImp = new InterfaceImplementer(); iImp.MethodToImplement(); iImp.ParentInterfaceMethod(); } public void MethodToImplement() { Console.WriteLine("MethodToImplement() called."); } public void ParentInterfaceMethod() { Console.WriteLine("ParentInterfaceMethod() called."); }

INTRODUCTION TO DELEGATE

A delegate is a C# language element that allows us to reference a method. Using a delegate allows the programmer to encapsulate a reference to a method inside a delegate object. The delegate object can then be passed to code which can call the referenced method, without having to know at compile time which method will be invoked. Unlike function pointers in C or C++, delegates are objectoriented, type-safe, and secure. A delegate declaration defines a type that encapsulates a method with a particular set of arguments and return type. For static methods, a delegate object encapsulates the method to be called. For instance methods, a delegate object encapsulates both an instance and a method on the instance.

If we have a delegate object and an appropriate set of arguments, we can invoke the delegate with the arguments.

INTRODUCTION TO DELEGATE
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, obje ct 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; } }

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 override string ToString() { return FirstName + " " + LastName; }


}

INTRODUCTION TO DELEGATE
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()); } } }

ANONYMOUS METHODS

An anonymous method is a method without a name - which is why it is called anonymous.

We don't declare anonymous methods like regular methods.


An anonymous method uses the keyword, delegate, instead of a method name. This is followed by the body of the method.
delegate void Printer(string s); class TestClass { static void Main() { // Instatiate the delegate type using an anonymous method: Printer p = delegate(string j) { System.Console.WriteLine(j); }; // Results from the anonymous delegate call: p("The delegate using the anonymous method is called."); // The delegate instantiation using a named method "DoWork": p = new Printer(TestClass.DoWork); // Results from the old style delegate call: p("The delegate using the named method is called."); } // The method associated with the named delegate: static void DoWork(string k) { System.Console.WriteLine(k); } }

INTRODUCTION TO EVENTS

Events provide a generally useful way for objects to signal state changes that may be useful to clients of that object.

Events are declared using delegates.


The publishing class defines a delegate. The subscribing class does two things: first, it creates a method that matches the signature of the delegate, and then it creates an instance of that delegate type encapsulating that method. When the event is raised, the subscribing class's methods are invoked through the delegate. A method that handles an event is called an event handler.

We can declare our event handlers as we would any other delegate.

INTRODUCTION TO EVENTS

By convention, event handlers in the .NET Framework always return void and take two parameters.

The first parameter is the "source" of the event (that is, the publishing object). The second parameter is an object derived from EventArgs.
Our event handlers will need to follow this design pattern. EventArgs is the base class for all event data. Other than its constructor, the EventArgs class inherits all its methods from Object, though it does add a public static field named Empty, which represents an event with no state (to allow for the efficient use of events with no state).

INTRODUCTION TO EVENTS

The following simple example shows a class, ListWithChangedEvent, which is similar to the standard ArrayListclass, but also invokes a Changed event whenever the contents of the list change.
// events1.cs using System; namespace MyCollections { using System.Collections; // A delegate type for hooking up change notifications. public delegate void ChangedEventHandler(object sender, EventArgs e); // A class that works just like ArrayList, but sends event // notifications whenever the list changes. public class ListWithChangedEvent: ArrayList { // An event that clients can use to be notified whenever the // elements of the list change. public event ChangedEventHandler Changed; // Invoke the Changed event; called whenever list changes protected virtual void OnChanged(EventArgs e) { if (Changed != null) Changed(this, e); } // Override some of the methods that can change the list; // invoke event after each public override int Add(object value) { int i = base.Add(value); OnChanged(EventArgs.Empty); return i; } public override void Clear() { base.Clear(); OnChanged(EventArgs.Empty); } public override object this[int index] { set { base[index] = value; OnChanged(EventArgs.Empty); } } }

INTRODUCTION TO EVENTS
namespace TestEvents { using MyCollections; class EventListener { private ListWithChangedEvent List; public EventListener(ListWithChangedEvent list) { List = list; // Add "ListChanged" to the Changed event on "List". List.Changed += new ChangedEventHandler(ListChanged); } // This will be called whenever the list changes. private void ListChanged(object sender, EventArgs e) { Console.WriteLine("This is called when the event fires."); } public void Detach() { // Detach the event and delete the list List.Changed -= new ChangedEventHandler(ListChanged); List = null; } } class Test { // Test the ListWithChangedEvent class. public static void Main() { // Create a new list. ListWithChangedEvent list = new ListWithChangedEvent(); // Create a class that listens to the list's change event. EventListener listener = new EventListener(list);

// Add and remove items from the list. list.Add("item 1"); list.Clear(); listener.Detach(); }
} }

INTRODUCTION TO EVENTS

Declaring an event To declare an event inside a class, first a delegate type for the event must be declared, if none is already declared. public delegate void ChangedEventHandler(object sender, EventArgs e); The delegate type defines the set of arguments that are passed to the method that handles the event. Multiple events can share the same delegate type, so this step is only necessary if no suitable delegate type has already been declared. Next, the event itself is declared. public event ChangedEventHandler Changed; An event is declared like a field of delegate type, except that the keyword event precedes the event declaration, following the modifiers. Events usually are declared public, but any accessibility modifier is allowed.

INTRODUCTION TO EVENTS

Invoking an event Once a class has declared an event, it can treat that event just like a field of the indicated delegate type. The field will either be null, if no client has hooked up a delegate to the event, or else it refers to a delegate that should be called when the event is invoked. Thus, invoking an event is generally done by first checking for null and then calling the event. if (Changed != null) Changed(this, e); Invoking an event can only be done from within the class that declared the event.

INTRODUCTION TO EVENTS

Hooking up to an event From outside the class that declared it, an event looks like a field, but access to that field is very restricted. The only things that can be done are: Compose a new delegate onto that field. Remove a delegate from a (possibly composite) field. This is done with the += and -= operators. To begin receiving event invocations, client code first creates a delegate of the event type that refers to the method that should be invoked from the event. Then it composes that delegate onto any other delegates that the event might be connected to using +=. // Add "ListChanged" to the Changed event on "List": List.Changed += new ChangedEventHandler(ListChanged);

When the client code is done receiving event invocations, it removes its delegate from the event by using operator -=.
// Detach the event and delete the list: List.Changed -= new ChangedEventHandler(ListChanged);

EXCEPTION HANDLING

The C# language's exception handling features help us deal with any unexpected or exceptional situations that occur when a program is running.
Exception handling uses the try, catch, and finally keywords to try actions that may not succeed, to handle failures when we decide that it is reasonable to do so, and to clean up resources afterward.
try { result = SafeDivision(a, b); Console.WriteLine("{0} divided by {1} = {2}", a, b, result); } catch (DivideByZeroException e) { Console.WriteLine("Attempted divide by zero."); } } }

class ExceptionTest { static double SafeDivision(double x, double y) { if (y == 0) throw new System.DivideByZeroException(); return x / y; } static void Main() { // Input for test purposes. Change the values to see // exception handling behavior. double a = 98, b = 0; double result = 0;

EXCEPTION OVERVIEW

Exceptions have the following properties: Exceptions are types that all ultimately derive from System.Exception. Use a try block around the statements that might throw exceptions. Once an exception occurs in the try block, the flow of control jumps to the first associated exception handler that is present anywhere in the call stack. In C#, the catch keyword is used to define an exception handler. If no exception handler for a given exception is present, the program stops executing with an error message. Do not catch an exception unless we can handle it and leave the application in a known state. If we catchSystem.Exception, rethrow it using the throw keyword at the end of the catch block. If a catch block defines an exception variable, we can use it to obtain more information about the type of exception that occurred. Exceptions can be explicitly generated by a program by using the throw keyword. Exception objects contain detailed information about the error, such as the state of the call stack and a text description of the error. Code in a finally block is executed even if an exception is thrown. Use a finally block to release resources, for example to close any streams or files that were opened in the try block.

DEFINING EXCEPTION CLASS

Programs can throw a predefined exception class in the System namespace (except where previously noted), or create their own exception classes by deriving from Exception. The derived classes should define at least four constructors: one default constructor, one that sets the message property, and one that sets the Message and InnerExceptionproperties. The fourth constructor is used to serialize the exception. New exception classes should be serializable. For example:
[Serializable()] public class InvalidDepartmentException : System.Exception { public InvalidDepartmentException() : base() { } public InvalidDepartmentException(string message) : base(message) { } public InvalidDepartmentException(string message, System.Exception inner) : base(message, inner) { } // A constructor is needed for serialization when an // exception propagates from a remoting server to the client. protected InvalidDepartmentException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } }

REFLECTION

Reflection provides objects (of type Type) that describe assemblies, modules and types.

We can use reflection to dynamically create an instance of a type, bind the type to an existing object, or get the type from an existing object and invoke its methods or access its fields and properties.
If we are using attributes in our code, reflection enables us to access them.
// Using GetType to obtain type information: int i = 42; System.Type type = i.GetType(); System.Console.WriteLine(type); // Using Reflection to get information from an Assembly: System.Reflection.Assembly info = typeof(System.Int32).Assembly; System.Console.WriteLine(info); The output is: mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

Output is:System.Int32

NULLABLE TYPE

Nullable types are instances of the System.Nullable<T> struct. A nullable type can represent the correct range of values for its underlying value type, plus an additional null value.

For e.g. A Nullable<bool> can be assigned the values true false, or null.
The ability to assign null to numeric and Boolean types is especially useful when we are dealing with databases and other data types that contain elements that may not be assigned a value.
// y is set to zero int y = num.GetValueOrDefault(); // num.Value throws an InvalidOperationException if num.HasValue is false try { y = num.Value; } catch (System.InvalidOperationException e) { System.Console.WriteLine(e.Message); } } }

class NullableExample { static void Main() { int? num = null; if (num.HasValue == true) { System.Console.WriteLine("num = " + num.Value); } else { System.Console.WriteLine("num = Null"); }

CHARACTERISTICS OF NULLABLE TYPE

Nullable types represent value-type variables that can be assigned the value of null. we cannot create a nullable type based on a reference type. (Reference types already support the null value.)
The syntax T? is shorthand for Nullable<T>, where T is a value type. The two forms are interchangeable. Assign a value to a nullable type just as we would for an ordinary value type, for example int? x = 10; ordouble? d = 4.108. A nullable type can also be assigned the value null: int? x = null.

Use the Nullable<T>.GetValueOrDefault method to return either the assigned value, or the default value for the underlying type if the value is null, for example int j = x.GetValueOrDefault();

CHARACTERISTICS OF NULLABLE TYPE

Use the HasValue and Value read-only properties to test for null and retrieve the value, as shown in the following example: if(x.HasValue) j = x.Value; The HasValue property returns true if the variable contains a value, or false if it is null. The Value property returns a value if one is assigned. Otherwise, a System.InvalidOperationException is thrown. The default value for HasValue is false. The Value property has no default value. we can also use the == and != operators with a nullable type, as shown in the following example: if (x != null) y = x;
Use the ?? operator to assign a default value that will be applied when a nullable type whose current value isnull is assigned to a non-nullable type, for example int? x = null; int y = x ?? -1;

Nested nullable types are not allowed. The following line will not compile: Nullable<Nullable<int>> n;

COLLECTIONS

Collections are specialized classes provided by .NET to store various data structures. Basically there are two types of collections.

The standard collections, which are found under the System.Collections namespace .
The generic collections, under System.Collections.Generic namespace. 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.

ARRAYLIST
For e.g.
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); } } }

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[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); } } }

Console.WriteLine(langs.Contains("C#"));

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 reallocate, which is an expensive operation.

LINKEDLIST

For e.g.
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); } }

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); }

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); }

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.
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); }

Вам также может понравиться