Enter your email address:


feedburner count

C# 2.0 : Nullable Types

Labels:

Problem

// User Class
public class User
{
private int userID;
private DateTime registeredDate;


public User() {}

public int UserID
{
get { return userID; }
set { userID = value; }
}

public DateTime RegisteredDate
{
get { return registeredDate; }
set { registeredDate = value; }
}
}


// Create User from a DataReader
public virtual User CreateUserFromReader(IDataReader reader)
{
User item
= new User();

item.UserID
= (int)reader["UserID"];
// throw exception if reader["RegisteredDate"] equals null
item.RegisteredDate = (DateTime)reader["RegisteredDate"];

return item;
}
Because C# 1.1 does not support null value for DateTime so the example above will throw exception if reader["RegisteredDate"] equals null.
Solution
Old schoold soltution :
// Create User from a DataReader
public virtual User CreateUserFromReader(IDataReader reader)
{
User item
= new User();

item.UserID
= (int)reader["UserID"];
if (!reader.IsDBNull(reader.GetOrdinal("RegisteredDate")))
{
item.RegisteredDate
= (DateTime)reader["RegisteredDate"];
}
else
{
item.RegisteredDate
= new DateTime(1900,1,1,0,0,0,0);
}

return item;
}
Now in C#2.0 we can resolve null problem by declaration RegisteredDate as nullable DateTime with ? symbol :

// User Class
public class User
{
private int userID;
private DateTime? registeredDate;


public User() {}

public int UserID
{
get { return userID; }
set { userID = value; }
}

public DateTime? RegisteredDate
{
get { return registeredDate; }
set { registeredDate = value; }
}
}


// Create User from a DataReader
public virtual User CreateUserFromReader(IDataReader reader)
{
User item
= new User();

item.UserID
= (int)reader["UserID"];
item.RegisteredDate
=
(reader.IsDBNull(reader.GetOrdinal(
"RegisteredDate"))) ?
null : (DateTime)reader["RegisteredDate"];
return item;
}
Nullable type
Nullable types are constructed using ? type modifier.
Example :
int? age;
string? name;
DateTime? birthday;

A nullable type has two public read-only properties: HasValue and Value. When HasValue is true, the Value property returns the contained value. When HasValue is false, an attempt to access the Value property throws an exception.
DateTime? registeredDay;

// throw exception if RegisteredDate is null
registeredDay = user.RegisteredDate;
if (user.HasValue)
{
registeredDay
= user.RegisteredDate
}
else
{
registeredDay
= null;
}
Null colalescence
C# 2.0 introduces a new operator called the null coalescing operator denoted by
double question marks ?? . If the instance is null, the value on the right is returned
otherwise the nullable instance value is returned.

int x = 10;
int? y = null;
int z = y ?? x;

response.write(z);
// z = 10

y
= 99;
int k = y ?? x;
response.write(k);
// k = 99




C# 2.0 : Partial types

Labels:

What is Partial types ?
Partial types is types that allow classes, structs, and interfaces to be broken into multiple pieces stored in different source files for easier development and maintenance. Additionally, partial types allow separation of machine-generated and user-written parts of types so that it is easier to augment code generated by a tool.

Problems
While it is good programming practice to maintain all source code for a type in a single file, sometimes a type becomes large enough that this is an impractical constraint. Furthermore, programmers often use source code generators (such as CodeSmith) to produce the initial structure of an application, and then modify the resulting code. Unfortunately, when source code is emitted again sometime in the future, existing modifications are overwritten.

Solution
A new type modifier, partial, is used when defining a type in multiple parts. The following is an example of a partial class that is implemented in two parts.

Part one :
public partial class Customer
{
private int id;
private string name;
private string address;
private List<Order> orders;

public Customer()
{
}
}

Part two :
public partial class Customer
{
public void SubmitOrder(Order order)
{
orders.Add(order);
}
public bool HasOutstandingOrders()
{
return orders.Count > 0;
}
}
When the two parts above are compiled together, the resulting code is the same as if the class had been written as a single unit:
public class Customer
{
private int id;
private string name;
private string address;
private List<Order> orders;

public Customer()
{
}

public void SubmitOrder(Order order)
{
orders.Add(order);
}

public bool HasOutstandingOrders()
{
return orders.Count > 0;
}
}




C# 2.0 : Anonymous Methods

Labels:

What is Anonymous Method ?
C# 2.0 introduce new method named Anonymous Methods. Anonymous Methods are Inline Delegate.

Old school Delegate :

this.btnLogin.Click += new System.EventHandler(this.btnLogin_Click);
void btnLogin_Click(object sender, System.EventArgs e)
{
Response.Write(
"tui ne");
}


Anonymous Method :

this.btnLogin.Click += delegate { Response.Write("tui ne"); }




C# 2.0 : Generic methods

Labels:

This is a typical non-generic method :

void AddMultiple(List<Customer> customers, params Customer[] values)
{
foreach (Customer value in values)
{
customers.Add(value);
}
}

In order to add mutiple customer into List :

List<Customer> customers = new List<Customer>();
AddMultiple(customers,
new Customer(),
new
Customer(), new Customer());

However, the method above only works with type . To have it work
with any List , the method must be written as a generic method.
A generic method has one or more type parameters specified in <
and > delimiters after the method name :

void AddMultiple<T>(List<T> customList, params T[] values)
{
foreach (T value in values)
{
customList.Add(value);
}
}

Finally, we can add any type to generic List :

List<int> listInteger = new List<int>();
AddMultiple
<int>(listInteger, 1, 2, 3, 4);

List
<Customer> customers = new List<Customer>;
AddMultiple
<Customer>(customers,
new
Customer(),
new Customer(),
new Customer(),
new Customer());

In the example above, since the first regular argument is type List
listInteger, and the subsequent arguments are of type int 1, 2, 3 ,
4
the compiler can reason that the type parameter must be int. Thus,
we can use shorter syntax without specifying the type parameter
(<int>) :
List<int> listInteger = new List<int>();
AddMultiple(listInteger,
1, 2, 3, 4);

The same for the second scenario :

List<Customer> customers = new List<Customer>();
AddMultiple(customers,
new Customer(),
new Customer(),
new Customer(),
new
Customer());




C# 2.0 : Constraints in Generics

Labels:

Problem

public class Dictionary<K, V>
{
public void Add(K key, V value)
{
...
if (key.CompareTo(x) < 0) {...} // Error, no CompareTo method
...
}
}

Since the type argument specified for K could be any type, the
only members that support CompareTo are memberss that implement
IComparable Interface such as Equals, GetHashCode, ToString...
A Compile-time error occurs in the example above.

Solution

public class Dictionary<K, V> where K: ICompareable
{
public void Add(K key, V value)
{
...
if (key.CompareTo(x) < 0) {...}
...
}
}

The Declaration above ensure that any type argument supplied for K
is a type that implements IComparable. It is possible to specify
any number of interface and type parameters as constraints :

public class Dictionary<K, V>
where K: ICompareable
<K>, IPersistable
where V: Entity
{
public void Add(K key, V value)
{
...
if (key.CompareTo(x) < 0) {...}
...
}
}





C# 2.0 : How to create Generics

Labels:

Generic Class with one parameter

This is a typical Non-generic Class :
public class List
{
object[] items;

public void Add(object item) {....}
public object this[int index] {...}
}
Generic Class : in order to create generics class we use the type argument T in < and > after class name.
public class List<T>
{
[T] items;

public void Add(T item) {....}
public T this[int index] {...}
}
Using Generic class :
List<int> listInteger = new List<int>;
listInteger.Add(
1);
listInteger.Add(
2);
listInteger.Add(
3);
listInteger.Add(
new Customer()); // Compile-time error

Note:
T : type argument.
List : is List of Integer type. The List type is called a constructed type. Every occurrence of T is replaced with the type argument int. When an instance of List is created, the native storage of the items array is an int[] rather than object[]. If we add a Customer into List , then compiler will report error.

Generic Class with more than one parameters

Generic type declarations may have any number of type parameters. The List example above has only one type parameter, but a generic Dictionary class might have two type parameters, one for the type of keys and one for the type of values.

public class Dictionary<K,V>
{
public void Add(K key, V value) {...}
public V this[K key] {...}
}
When Dictionary is used, two type arguments would have to be supplied :

Dictionary<string, Customer> dict = 
new
Dictionary<string, Customer>();
dict.Add(
"Hung", new Customer());
Customer customer
= dict["Hung"];




C# 2.0 Generics

Labels:

Generics Overview

  • Use generic types to maximize code reuse, type safety, and performance.

  • The most common use of generics is to create collection classes.

  • The .NET Framework class library contains several new generic collection classes in the System.Collections.Generic namespace. These should be used whenever possible in place of classes such as ArrayList in the System.Collections namespace.

  • You can create your own generic interfaces, classes, methods, events and delegates.

  • Generic classes may be constrained to enable access to methods on particular data types.

Why Generics ?

Type safety casting & performance:

Using generics is not only safer than general old collection class (such as ArrayList, Collections...) but also significantly faster.

C# 1.1 :
ArrayList customers = new ArrayList();
Customer customer
= new Customer();

// Boxing --> descrease performance. No type-checking
customers.Add(customer);
// Boxing --> descrease performance. No type-checking
customers.Add("Some string");

// throw exception
// Customer customer = customers[0];

C# 2.0 :

List<Customer> customers = new List<Customers>();
Customer customer
= new Customer();

// No Boxing, no casting --> increase performance.
customers.Add(customer);

// Type-Checking : Compile-time error
customers.Add("Some string");

// No UnBoxing, no casting --> increase performance .
// Not throw exception

Customer customer2 = customers[0];

// UnBoxing --> decrease performance
Customer customer2 = (customer)customers[0];