C# 2.0 : Nullable Types
Problem
// User Classpublic class UserBecause C# 1.1 does not support null value for DateTime so the example above will throw exception if reader["RegisteredDate"] equals null.
{
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;
}
Solution
Old schoold soltution :
// Create User from a DataReader
public virtual User CreateUserFromReader(IDataReader reader)Now in C#2.0 we can resolve null problem by declaration RegisteredDate as nullable DateTime with ? symbol :
{
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;
}
// User ClassNullable type
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 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;Null colalescence
// throw exception if RegisteredDate is null
registeredDay = user.RegisteredDate;
if (user.HasValue)
{
registeredDay = user.RegisteredDate
}
else
{
registeredDay = null;
}
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
Wednesday, August 30, 2006 | 0 Comments
C# 2.0 : Partial types
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 CustomerWhen 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 void SubmitOrder(Order order)
{
orders.Add(order);
}
public bool HasOutstandingOrders()
{
return orders.Count > 0;
}
}
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;
}
}
Wednesday, August 30, 2006 | 0 Comments
C# 2.0 : Anonymous Methods
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"); }
Wednesday, August 30, 2006 | 0 Comments
C# 2.0 : Generic methods
This is a typical non-generic method :
void AddMultiple(List<Customer> customers, params Customer[] values)Finally, we can add any type to generic List :
{
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);
}
}
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());
Wednesday, August 30, 2006 | 0 Comments
C# 2.0 : Constraints in Generics
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) {...}
...
}
}
Wednesday, August 30, 2006 | 0 Comments
C# 2.0 : How to create Generics
Generic Class with one parameter
This is a typical Non-generic Class :public class ListGeneric Class : in order to create generics class we use the type argument T in < and > after class name.
{
object[] items;
public void Add(object item) {....}
public object this[int index] {...}
}
public class List<T>Using Generic class :
{
[T] items;
public void Add(T item) {....}
public T this[int index] {...}
}
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
Generic Class with more than one parameters
Generic type declarations may have any number of type parameters. The Listpublic class Dictionary<K,V>When Dictionary
{
public void Add(K key, V value) {...}
public V this[K key] {...}
}
Dictionary<string, Customer> dict =
new Dictionary<string, Customer>();
dict.Add("Hung", new Customer());
Customer customer = dict["Hung"];
Wednesday, August 30, 2006 | 0 Comments
C# 2.0 Generics
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];
Monday, August 28, 2006 | 0 Comments