Tuesday, July 29, 2008

c# - notes - part2

Arrays
Single-Dimensional Arrays
The type of each array declared is given firstly by the type of basic elements it can hold, and secondly by the number of dimensions it has. Single-dimensional arrays have a single dimension (ie, are of rank 1). They are declared using square brackets, eg: int[] i = new int[100];
Rectangular Arrays
int[,] squareArray = {{1, 2, 3}, {4, 5, 6}};
Jagged Arrays
Using jagged arrays, one can create multidimensional arrays with irregular dimensions. This flexibility derives from the fact that multidimensional arrays are implemented as arrays of arrays.

Jump Statements
break
continue
goto
return
throw


Enumerators
The enum keyword is used to declare an enumeration, a distinct type consisting of a set of named constants called the enumerator list. Every enumeration type has an underlying type, which can be any integral type except char. The default underlying type of the enumeration elements is int. By default, the first enumerator has the value 0, and the value of each successive enumerator is increased by 1.

enum Days {Sat, Sun, Mon, Tue, Wed, Thu, Fri};

long x = (long) Days. Mon;
long y = (long) Days. Wed;


structure

A structure in C# is simply a composite data type consisting of a number elements of other types. A C# structure is a value type and the instances or objects of a structure are created in stack. The structure in C# can contain fields, methods, constants, constructors, properties, indexers, operators and even other structure types.

struct
{
//Structure members
}
Where the modifier can be private, public, internal or public. The struct is the required keyword.

struct MyStruct
{
public int x;
public int y;
}
MyStruct ms = new MyStruct();
ms.x = 10;
ms.y = 20;

* A structure or struct can contain only fields, methods, Etc.,
* In struct we can't initialize the variable whereas in class it can be possible
* It must be initialized either through function or using object
* Fields can't be given initial values at the time of creation.
* struct can't have a constructor.
* struct can't support the concept of inheritance
* We can derive a structure from an interface
* We can't inherit from sealed class
* A structure could not inherit from a class, the reverse is also true
* You can't declare a struct as sealed, because by default it is sealed
* A structure declare as abstract can't be used as a base class, i.e., be used in a derivation
* No destructor for struct
* struct are created on the stack and die when we reach the closing brace

C# structs are useful for small data structures that have value semantics. Complex numbers
Since structs doesn't support inheritance, we can't use the keywords virtual, override, new, abstract etc with a struct methods. C# struct types are never abstract and are always implicitly sealed. The abstract or sealed modifiers are not permitted in a struct declaration.
Since inheritance is not supported for structs, the declared accessibility of a struct member can't be protected or protected internal. Since all struct types are implicitly inherit from object class, it is possible to override the methods of the object class inside a struct by using the keyword override. Remember that this is special case in C# structs

Sealed Class :

The sealed modifier can be applied to classes, instance methods and properties.
A sealed class cannot be inherited.
A sealed method overrides a method in a base class, but itself cannot be overridden further in any derived class.
When applied to a method or property, the sealed modifier must always be used with override (C# Reference).
A sealed class cannot be used as a base class. For this reason, it cannot also be an abstract class. Sealed classes are primarily used to prevent derivation. Because they can never be used as a base class, some run-time optimizations can make calling sealed class members slightly faster. Sealing a class means one can not derive from it. Sealing a method means one can not override it. In C# structs are implicitly sealed; therefore, they cannot be inherited. If we try to inherit from a sealed class in another class we will get compile time error about Inconsistent accessibility

Override Methods
Overriding in C# makes use of the "override" keyword. To override a method means to replace it with a new way of handling data. Here's an example of what I mean:

It is an error to include - new, static, or virtual.
An override method declaration may include the abstract modifier. This enables a virtual method to be overridden by an abstract method.

Virtual methods
Virtual methods allow object oriented languages to express polymorphism.This means that a derived class can write a method with the same signature as a method in its base class, and the base class will call the derived class's method.By default in java, all methods are virtual. In C# like C++, the virtual keyword is needed to specify that a method should override a method (or implementaion an abstract method) of its base class.
Class B {public virtual void foo () {}}ClassD : B {public override void foo () {}}
When a virtual method is invoked, the run-time type of the object is checked for an overriding member. The overriding member in the most derived class is called, which might be the original member, if no derived class has overridden the member. (
By default, methods are non-virtual. You cannot override a non-virtual method.
Attemting to override a non-virtual method will results in a compile-time error unless the "new" keyword is added to the declaration, indicating the method is intentionally hiding the base clas's method.
You cannot use the virtual modifier with the following modifiers:
static abstract override

Method Hiding
if a method is not overriding the derived method, it is hiding it. A hiding method has to be declared using the new keyword

extern
Use the extern modifier in a method declaration to indicate that the method is implemented externally. A common use of the extern modifier is with the DllImport attribute
Combining Method Overriding and Hiding
Methods of a derived class can both be virtual and at the same time hide the derived method. In order to declare such a method, both keywords virtual and new have to be used in the method declaration:
class A
{
public void Foo() {}
}

class B : A
{
public virtual new void Foo() {}
}

A class C can now declare a method Foo() that either overrides or hides Foo() from class B:
class C : B
{
public override void Foo() {}
// or
public new void Foo() {}
}
Note: Only methods in base classes need not override or hide derived methods. All methods in derived classes require to be either defined as new or as override.

Static & Non Static

A static method belongs to the class and a non-static method belongs to an object of a class. That is, a non-static method can only be called on an object of a class that it belongs to. A static method can however be called both on the class as well as an object of the class. A static method can access only static members. A non-static method can access both static and non-static members because at the time when the static method is called, the class might not be instantiated (if it is called on the class itself). In the other case, a non-static method can only be called when the class has already been instantiated. A static method is shared by all instances of the class. These are some of the basic differences. I would also like to point out an often ignored difference in this context. Whenever a method is called in C++/Java/C#, an implicit argument (the 'this' reference) is passed along with/without the other parameters. In case of a static method call, the 'this' reference is not passed as static methods belong to a class and hence do not have the 'this' reference


Polymorphism
Through inheritance, a class can be used as more than one type;
it can be used as its own type, any base types, or any interface type if it implements interfaces.
This is called polymorphism.

polymorphism realizes through the using of keyword virtual and override


Dynamic dispatch

A a = new B b

Operator overloading
also known as overloading, provides a way to define and use operators such as +, -, and / for user-defined classes or structs. It allows us to define/redefine the way operators work with our classes and structs. This allows programmers to make their custom types look and feel like simple types such as int and string. It consists of nothing more than a method declared by the keyword operator and followed by an operator.
There are three types of over loadable operators called
Unary
Binary
Conversion
Note that all the overloaded operator methods are named "operator." Further, all operator methods in C# are static

// Normal way of adding two instance of matrix object
Matrix result = mat1.Add(mat2); // instance
// Using Operator overloading ( + )
Matrix result = mat1 + mat2;

Sample ex:
class Fps
{
private int feet, inch;

public Fps()
{

}

public Fps(int f, int i)
{
feet = f;
inch = i;
}
//Some code
}

// Pass Fps object twice
// Syntax for operator over loading( + )
public static Fps operator + (Fps obj1, Fps obj2)
{
Fps temp = new Fps();
temp.feet = obj1.feet + obj2.feet;
temp.inch = obj1.inch + obj2.inch;

if (temp.inch > 12)
{
temp.feet++;
temp.inch -= 12;
}

return temp;
}




///
/// Increment the counter by one.
///

/// Counter to increment
/// Incremented counter
public static MyCounter operator ++(MyCounter Counter)
{
Counter.CounterValue++;
return Counter;
}



Delegate
Delegate is type which holds the method(s) reference in an object.
it is also reffered as a type safe function pointers.

If we look at C++ there is a feature called callback function. This feature uses Pointers to Functions to pass them as parameters to other functions. Delegate is a similar feature but it is more type safe,
A delegate can hold reference/s to one more more functions and invoke them as and when needed.

Advantages:

.Encapsulating the method's call from caller
.Effective use of Delegate improves the performance of application.
.used to call a method asynchronously.

Declaration:

public delegate type_of_delegate delegate_name()

Example : public delegate int mydelegate(int delvar1,int delvar2)

Note:
.you can use delegate without parameter or with parameter list
.you should follow the same syntax as in the method
(if you are referring the method with two int parameters and int return type
the delegate which you are declaring should be the same format.This is how it
is reffered as type safe function pointer)

Sample Program using Delegate :

public delegate double Delegate_Prod(int a,int b);

class Class1
{
static double fn_Prodvalues(intval1,int val2)
{
return val1*val2;
}
static voidMain(string[] args)
{


//Creating the DelegateInstance
Delegate_Prod delObj = newDelegate_Prod(fn_Prodvalues);


Console.Write("PleaseEnter Values");

int v1 =Int32.Parse(Console.ReadLine());
int v2 =Int32.Parse(Console.ReadLine());

//use a delegate forprocessing

double res =delObj(v1,v2);
// Delegate search for the same method and execute the code and give the result
Console.WriteLine ("Result:"+res);
Console.ReadLine();

}
}


Explanation:

Here I have used a small programwhich demonstrates the use of delegate.
The delegate "Delegate_Prod" isdeclared with double return type and which
accepts only two integerparameters.
Inside the Class the method namedfn_Prodvalues is defined with double return
type and two integerparameters.(The delegate and method is having the same signature and parameterstype)
Inside the Main method the delegateinstance is created and the function name is passed to the delegate instance asfollowing.
Delegate_Prod delObj = newDelegate_Prod(fn_Prodvalues);
After this we are accepting the twovalues from the user and passing those values to the delegate
as we do using method.
delObj(v1,v2);
Here delegate object encapsulatesthe method functionalities and return the result as we specified in the method.

delegate is not a standalone construction. it's a class.
This can be from either of the two classes from System.Delegate or System.MulticastDelegate.
MulticastDelegate
It is a Delegate which holds the reference of more than onemethod.
Multicast delegates must containonly methods that return void, else there is a run-timeexception.


Events:
Events are the messages sent by an object to indicate the occurrence of an event. Event can also be defined as a member that enables an object to provide notification. Events provide a very powerful means of inter-process communication. The most familiar example of events are graphical user interface, events are fired when any control is clicked on the GUI.
Events are not used only for graphical user interfaces. Events provide a generally useful way for objects to signal state changes that may be useful to the client of that object. In C# events are used with delegates. In event communication the event raiser class doesn't know who is going to handle the event now the delegates comes into play that acts as an intermediary between the source and the receiver.
Button b1=new Button();
b1.Parent=this;
b1.Location=new Point(o_intXaxis,o_intYaxis);
b1.Name="Click1";
b1.Text="Click Me";
ClickMe+=new IamClicked(Show);
ClickMe();
public void Show()
{
MessageBox.Show("JUST BORN");
}


Abstract Class
An abstract class is a special kind of class that cannot be instantiated.
An abstract class is only to be sub-classed (inherited from).
It only allows other classes to inherit from it but cannot be instantiated.
Advantage is that it enforces certain hierarchies for all the subclasses.
It is a kind of contract that forces all the subclasses to carry on the same hierarchies or standards.

Interface
An interface is not a class. It is an entity that is defined by the word Interface.
An interface has no implementation; it only has the signature or in other words
Just the definition of the methods without the body. As one of the similarities to Abstract class,
it is a contract that is used to define hierarchies for all subclasses or it defines specific set of methods and their arguments.
The main difference between them is that a class can implement more than one interface but can only inherit from one abstract class. Since C# doesn’t support multiple inheritance, interfaces are used to implement multiple inheritance.
Feature Interface Abstract class
Multiple inheritance A class may inherit several interfaces. A class may inherit only one abstract class.
Default implementation An interface cannot provide any code, just the signature. An abstract class can provide complete, default code and/or just the details that have to be overridden.
Access Modfiers An interface cannot have access modifiers for the subs, functions, properties etc everything is assumed as public An abstract class can contain access modifiers for the subs, functions, properties
Core VS Peripheral Interfaces are used to define the peripheral abilities of a class. In other words both Human and Vehicle can inherit from a IMovable interface. An abstract class defines the core identity of a class and there it is used for objects of the same type.
Homogeneity If various implementations only share method signatures then it is better to use Interfaces. If various implementations are of the same kind and use common behaviour or status then abstract class is better to use.
Speed Requires more time to find the actual method in the corresponding classes. Fast
Adding functionality (Versioning) If we add a new method to an Interface then we have to track down all the implementations of the interface and define implementation for the new method. If we add a new method to an abstract class then we have the option of providing default implementation and therefore all the existing code might work properly.
Fields and Constants No fields can be defined in interfaces An abstract class can have fields and constrants defined

Interface Example
interface IPerson
{
void Eat();
void Sleep();
int Weight
{
set;
get;
}
}

In order to use this interface, you must declare your class in the same way that you declare a class inheriting from any other object.


Example
public class Man:IPerson
{
int iWeight;

public Man()
{
}

public void Eat()
{
MessageBox.Show("Man:Eat");
}

public void Sleep()
{
MessageBox.Show("Man:Sleep");
}

public int Weight
{
set
{
iWeight = value;
}
get
{
return iWeight;
}
}

static void Main()
{
Man i = new Man();
i.Eat();
i.Sleep();
}

}


You get the following result when you run the above code.
Man:Eat
Man:Sleep

It is important to note here that an interface is very different from a base class. An interface is implemented, not extended.
1.A class can implement multiple interfaces.
2.An interface cannot contain data declarations but you can declare properties.
3.All method declarations in an interface are public.
4.There can be no implementation in an interface.
5.The class implementing the interface must provide implementation code.
6.An interface can be derived from another interface




Indexers In C#

C# introduces a new concept known as Indexers which are used for treating an object as an array. The indexers are usually known as smart arrays in C# community. Defining a C# indexer is much like defining properties. We can say that an indexer is a member that enables an object to be indexed in the same way as an array.
this [argument list]
{
get
{
// Get codes goes here
}
set
{
// Set codes goes here
}
}
Where the modifier can be private, public, protected or internal. The return type can be any valid C# types. The 'this' is a special keyword in C# to indicate the object of the current class. The formal-argument-list specifies the parameters of the indexer. The formal parameter list of an indexer corresponds to that of a method, except that at least one parameter must be specified, and that the ref and out parameter modifiers are not permitted. Remember that indexers in C# must have at least one parameter. Other wise the compiler will generate a compilation error.
The following program shows a C# indexer in action
using System;
using System.Collections;

class MyClass
{
private string []data = new string[5];
public string this [int index]
{
get
{
return data[index];
}
set
{
data[index] = value;
}
}
}


class MyClient
{
public static void Main()
{
MyClass mc = new MyClass();
mc[0] = "Rajesh";
mc[1] = "A3-126";
mc[2] = "Snehadara";
mc[3] = "Irla";
mc[4] = "Mumbai";
Console.WriteLine("{0},{1},{2},{3},{4}",mc[0],mc[1],mc[2],mc[3],mc[4]);
}
}

serialization

Serialization is the process of saving the current state of any object into persistent storage (like file system), so that it can be retrieved later (Deserialize) and re create the same object.

For example, you have an object called student. You assign some values into the properties of this student object and serialze this object into a file. You can keep this file and de serialize any time later to re produce your student to the saved state.

What is serializable class

If a class can be serialized by using the builtin serialization features in .NET, that class is called serializable class. Most of the classes provided by .NET Framework is serializable.

Different types of Serialization
There are two broad categories of serialization in .NET
1. XML Serialization
2. Binary Serialization

XML Serialization serializes the object into an xml file. This file is human readable and can be shared with other applications.

Binary serialization is more efficient, but the serialized file is in binary format. It may not make any sense for a human being to open this file and understand what it contains. It is a stream of bytes.

Can I make my own classes serializable ?

Yes, it is very easy to make any class serializable. Simply add an attribute called 'Serializable' just above the class declaration and your class is serializable - means anybody can write few lines of C# code to save the state of the instance of your class into disk and retrieve (deserialize) later.

[Serializable]
public class MyClass
{
public string name;
public string adress;
}

How to serialize classes ?

The following samples demonstrate how to do XML Serialization and Binary Serialization using .NET classes.

We are serializing an 'ArrayList' object into disk and deserializing it again from the disk into another array list.

If you are not familiar with ArrayList - it is a collection class provided by .NET Framework, which can hold a list of any objects. The sample shown below uses an ArrayList which holds a list of strings.

XML Serialization

XmlSerializer serializer = new XmlSerializer( typeof(ArrayList) );

TextWriter writer = new StreamWriter( @"MyApplicationData.xml" );


Deserialization

Stream stream = new FileStream( @"MyApplicationData.dat", System.IO.FileMode.Open );


Binary Serialization

Stream stream = new FileStream( @"MyApplicationData.dat", System.IO.FileMode.Create );


Deserializing the binary data

Stream stream = new FileStream( @"MyApplicationData.dat", System.IO.FileMode.Open );


Where is Serialization used

Serialization has lot of uses in application development. One important purpose is to transmit data between application domains. Webservices and remoting uses serialization/deserialization technique to exchange data.

When you call a webservice and pass parameters, the parameters are serialized into XML data and send to the server. When the webservice return data, the result is serialized into XML and returned to the caller. This means, you can pass only serializable data in web service calls.

In Remoting, you can choose either Binary or SOAP(XML) formatting.
In addition to the above, you can use serialization as a way to store the application data into files. For example, you want to save the last logged in user name, but you don't have a database. You can serialize the user object itself or serialize just the name of the user into disk. When you start the application next time, you can deserialize the user name from the serialized data. Many of the applications use this serialization mechanism to remember the user settings and application data.

Enterprise Library
Enterprise Library consists of a collection of application blocks and a set of core features such as object generation and configuration mechanisms. All of these are reusable software components designed to assist developers with common enterprise development challenges.

Benefits of Enterprise Library
Enterprise Library is a collection of application blocks and services intended for use by developers who build complex, enterprise-level applications. These applications are typically deployed widely and have interdependencies with other application and systems. In addition, they generally have strict security, reliability, and performance requirements.
The goals of Enterprise Library are the following:
Consistency. All Enterprise Library application blocks feature consistent design patterns and implementation approaches.
Extensibility. All application blocks include defined extensibility points that allow developers to customize the behavior of the application blocks by adding their own code.
Ease of use. Enterprise Library offers numerous usability improvements, including a graphical configuration tool, a simpler installation procedure, and clearer and more complete documentation and samples.
Integration. Enterprise Library application blocks are designed to work well together and are tested to make sure that they do. It is also possible to use the application blocks individually.

Application Block
Microsoft has developed and released Application Blocks for Data Access and Exception Management for using in .NET applications. These application blocks provide the .NET developer not only the ready to use code inside the application, but also the code which was built by encapsulating the best practices by Microsoft



Generics
A generic is a code template that can be applied to use the same code repeatedly. Each time the generic is used, it can be customized for different data types without needing to rewrite any of the internal code.
Generics give you the ability to create a generic methods or a generic type by defining a placeholder for method arguments or type definitions, which are specified at the time of invoking the generic method or creating the generic type.

You can find a lot of generic collections in the System.Collections.Generic just like:
1. List
2. Dictionary
3. Queue
4. Stack


//Can only contain int type
List intList = new List();

//no boxing
intList.Add(10);

//no unboxing
int x = intList[0];

//Can only contain Employee objects
List empList = new List();

//no boxing
empList.Add(new Employee("Amr", "Ashush", 23));

//no unboxing
Employee e = empList[0];

The problem with programming generically is that sometimes there isn't a useful base class or interface that's shared by all the types you want to support. Usually, the only solution is to build a weakly typed class that treats everything as the base type Object.
The perfect example of this problem is the System.Collections.ArrayList class. ArrayList is an all-purpose dynamically self-sizing collection. It can hold ordinary .NET objects or your own custom objects. In order to support this, ArrayList treats everything as the base Object type. The problem is there's no way to impose any restrictions on how ArrayList works. For example, if you want to use the ArrayList to store a collection of Customer objects, you have no way to be sure that a faulty piece of code won't accidentally insert strings, integers, or any other type of object. These mistakes won't raise an exception, although they might lead to more subtle and insidious errors later on. As a result, one of the most common ingredients in a .NET application is custom collection classes that derive from ArrayList but are strongly typed. The .NET class library is swamped with dozens upon dozens of strongly typed collections classes.

Nullable Types
Nullable types are instances of the System.Nullable struct. A nullable type can represent the normal range of values for its underlying value type, plus an additional null value. For example, a Nullable, pronounced "Nullable of Int32," can be assigned any value from -2147483648 to 2147483647, or it can be assigned the null value. A Nullable can be assigned the values true or false, or null. The ability to assign null to numeric and Boolean types is particularly useful when dealing with databases and other data types containing elements that may not be assigned a value.

Nullable Types Overview
Nullable types have the following characteristics:
· Nullable types represent value-type variables that can be assigned the value of null. You cannot create a nullable type based on a reference type. (Reference types already support the null value.)
· The syntax T? is shorthand for System.Nullable, where T is a value type. The two forms are interchangeable.
· Assign a value to a nullable type in the same way as for an ordinary value type, for example int? x = 10; or double? d = 4.108;
· Use the System.Nullable.GetValueOrDefault property 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();
· Use the HasValue and Value read-only properties to test for null and retrieve the value, for 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 a nullable type variable sets HasValue to false. The Value is undefined.
· Use the ?? operator to assign a default value that will be applied when a nullable type whose current value is null 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> n;
?? Operator (C# Reference)
The ?? operator returns the left-hand operand if it is not null, or else it returns the right operand.
// ?? operator example.
int? x = null;

// y = x, unless x is null, in which case y = -1.
int y = x ?? -1;



Iterator

An iterator is a method, get accessor, or operator that performs a custom iteration over an array or collection class by using the yield keyword. The yield return statement causes an element in the source sequence to be returned immediately to the caller before the next element in the source sequence is accessed. Although you write an iterator as a method, the compiler translates it into a nested class that is, in effect, a state machine. This class keeps track of the position of the iterator as long the foreach loop on the client code continues.
Note:
To see what the compiler does behind the scenes, use the ILDASM.exe tool to view the intermediate language (IL) code that is generated for an iterator method.
An iterator is invoked from client code by using a foreach statement. For example, you can create an iterator for a class that returns the elements in reverse order, or that performs an operation on each element before the iterator returns it. When you create an iterator for your class or struct, you do not have to implement the whole IEnumerator interface. When the compiler detects your iterator, it will automatically generate the Current, MoveNext and Dispose methods of the IEnumerator or IEnumerator<(Of <(T>)>) interface.

Iterators Overview
An iterator is a section of code that returns an ordered sequence of values of the same type.
An iterator can be used as the body of a method, an operator, or a get accessor.
The iterator code uses the yield return statement to return each element in turn. yield break ends the iteration.
Multiple iterators can be implemented on a class. Each iterator must have a unique name just like any class member, and can be invoked by client code in a foreach statement as follows: foreach(int x in SampleClass.Iterator2){}.
The return type of an iterator must be IEnumerable, IEnumerator, IEnumerable<(Of <(T>)>), or IEnumerator<(Of <(T>)>).

Iterators are the basis for the deferred execution behavior in LINQ queries.
The yield keyword is used to specify the value, or values, that are returned. When the yield return statement is reached, the current location is stored. Execution is restarted from this location the next time that the iterator is called.
Iterators are especially useful with collection classes, providing an easy way to iterate complex data structures such as binary trees.

public System.Collections.IEnumerator GetEnumerator()
{
for (int i = 0; i < 10; i++)
{
yield return i;
}
}
The presence of the GetEnumerator method makes the type an enumerable type and allows using the foreach statement. If the method above was part of a class definition for ListClass, then it would be possible to use foreach on the class like this:
static void Main()
{
ListClass listClass1 = new ListClass();

foreach (int i in listClass1)
{
System.Console.WriteLine(i);
}
}
The foreach statement invokes ListClass.GetEnumerator() and uses the returned enumerator to iterate through the values. For an example of how to create a generic iterator that returns a IEnumerator<(Of <(T>)>) interface,
Why does C#'s iterators feature spit out a class definition instead of a struct definition?

The iterators feature in C# generates classes that implement the enumerators required. This is detailed in the C# Specification. Why doesn't it use structs, which would be more efficient.

A:

There are two reasons.

(1) Naming. We generate classes that implement the enumerator interfaces and then use only the interface types in the public protocol. That way the names of the generated classes are purely an implementation detail. This is highly desirable from a versioning perspective. With a struct-based implementation, to get any of the efficiencies associated with structs we would have to use their types in the public protocol (using interfaces the structs would just get boxed). That in turns means we'd have to invent a name mangling scheme for the structs. In particular, iterators returning IEnumerable would be complicated because a type could have multiple such members that differ only in their parameter list, meaning that the parameter list would have to be part of the mangled name.

(2) Structs don't work in recursive cases. For example, a TreeNode type could implement an iterator that recursively iterates first the left and then the right subtrees by foreach-ing contained members that are also of type TreeNode. With a struct-based implementation this would translate into an enumerator struct that contains a field of its own type--which isn't possible. (Think of it this way: A foreach statement obtains an enumerator and stores that in a local variable. In iterators, local variables are transformed into fields in the enumerator. A recursive iterator would therefore create a struct with a member of its own type.) You could argue that we can detect whether or not iterators are recursive and adjust our code generation scheme accordingly. However, you then end up with a versioning problem when a previously non-recursive iterator changes its (supposedly private) implementation to become recursive.


Patial Class
partial classes mean that your class definition can be split into multiple physical files. Logically, partial classes do not make any difference to the compiler. During compile time, it simply groups all the various partial classes and treats them as a single entity
One of the greatest benefits of partial classes is that it allows a clean separation of business logic and the user interface (in particular the code that is generated by the visual designer). Using partial classes, the UI code can be hidden from the developer, who usually has no need to access it anyway. Partial classes will also make debugging easier, as the code is partitioned into separate files.

Here are some good reasons to use partial classes:
1. They allow programmers on your team to work on different parts of a class without needing to share the same physical file. While this is useful for projects that involve big class files, be wary: If you find your class file getting too large, it may well signal a design fault and refactoring may be required.
2. The most compelling reason for using partial class is to separate your application business logic from the designer-generated code. For example, the code generated by Visual Studio 2005 for a Windows Form is kept separate from your business logic (we will discuss this in a later section). This will prevent developers from messing with the code that is used for the UI. At the same time, it will prevent you from losing your changes to the designer-generated code when you change the UI.
3. Besides using the "partial" keyword for classes, you can also use it for structures and interfaces.




Typed Dataset
we can specify the Data type when we create a DataColumn for a DataTable. This is to enforce the runtime Type-safety for the column so that only data of specified data type can be stored in the column. In the same way, in most of the cases we prefer to make a DataSet itself as Type-safe so as to protect it from runtime mismatch. Hence Typed DataSets generate classes that expose each object the in the DataSet in Type-safe manner. These classes inherits directly from DataSet class.
difference with normal dataset is that the sehema is already present for the same. Hence any mismatch in the column will generate compile time errors rather than runtime error as in the case of normal dataset. Also accessing the column value is much easier than the normal dataset as the column definition will be available in the schema.

No comments: