Archive

Archive for October, 2006

CLR Generics – Bibliography

October 23, 2006 1 comment
Categories: .NET Framework

CLR Generics – Comparing with other generics implementations

October 23, 2006 1 comment
Java
Java implements generics by type erasures and full code sharing. This means a few things to us as developers.
Runtime type information is lost.
Only reference types can be used as type parameters for generics.
The plus the java implementation brings in is that the generated bytecode can run on Java 1.4 JVM too. No JVM updates are required. The JVM itself is blind to generics. It is only the compiler which has been updated.
 
C++
In C++ generics are implemented using full code specialization during compiler time. This results in code bloat. Also another problem is that mos of the C++ generics implentations do not offer the strong type checking offered by CLR when it comes to calling methods on generic type parameters.
 
C++ generics offers operator support, which is a painful miss in the CLR implementation.
 
Categories: .NET Framework

CLR Generics – Notable BCL Additions

October 22, 2006 1 comment
System.Collections.Generics is probably the most popular which offer strongly typed generic based collections over their 1.1 counterparts in System.Collections.

Generic based collection Non Generic equivalent
List ArrayList
Dictionary Hashtable
SortedDictionary SortedList
Stack Stack
Queue Queue
LinkedList
IList IList
IDictionary IDictionary
ICollection ICollection
IEnumerable IEnumerable
IEnumerator IEnumerator
IComparable IComparable
IComparer IComparer

System.Nullable introduces nullable value types to CLR. You cannot assign value types like int, long, float, double etc to nulls in 1.1. This would be a pain especially if you are reading a nullable integer field from the database.

Categories: .NET Framework

CLR Generics – Internals

October 22, 2006 1 comment
IL Extensions:
The IL for List<T> looks like:
.class public auto ansi serializable beforefieldinit System.Collections.Generic.List`1<T>
Notice the backtick ‘`’ followed by arity and then followed by type parameters.
The IL for the void Add(T item) looks like:
.method public hidebysig newslot virtual final
    instance void  Add(!T item) cil managed
The _items array of type T is represented as
!0[] class System.Collections.Generic.List`1<!T>::_items
The !0 says this is a place holder and will be replaced with the actual type during code generation by the JIT. 0 is the index of the type paraeter.
 
Traditional generic implementations have followed the following routes to implement Generics.
No Specialization: Possible if every type parameter is represented as a boxed reference type. This will require boing / unboxing still.
Full Specialization: A new copy of code is generated for each specialization. The drawback being the code explosion / increased working set size.
Mixed Code Specialization / Sharing: Share code if type representations are compatible. Else specialize code. Value type representations are considered incompatible whereas reference type representations are considered compatible.
 
CLR takes the mixed mode and Specialization happens during JIT time.
 
Categories: .NET Framework

CLR Generics – Benefits and limitations

October 22, 2006 1 comment
Benefits of using generics

  • Code reuse
  • Compile time type checking
  • Performance benefits by avoiding boxing, unboxing for value types and also type compatibility checks involved with casts are needed for value types as well as reference types

A serious limitation of CLR Generics
Generic type variables cannot use operators. Isn’t it a serious one. A few workarounds http://blogs.msdn.com/ericgu/archive/2003/11/14/52852.aspx
http://www.codeproject.com/csharp/genericnumerics.asp

Categories: .NET Framework

CLR Generics – Other interesting trivia

October 22, 2006 1 comment
Default keyword
Inititalizing a generic to a default is not possible in case of value types. In case of reference types it is as easy as "T myVar=null;". In case of value types this is illegal. For value types the C# language has been extended using a new keyword default. "T myVar = default(T);"

Generic Interfaces, Delegates, Methods: In addition to Generic classes there can be Generic interfaces, Generic delegates and Generic methods. Let us just see an example of each.

public interface IEnumerator : IDisposable, IEnumerator {
	T Current { get; }
}
public delegate void EventHandler (
	object sender, TEventArgs e) where TEventArgs : EventArgs;
public static class Interlocked {
	public static T Exchange( ref T location1, T value) where T : class { ... }
	// Other members and implementation elided for clarity
}

Properties, Indexers, Events, Operators, Constructors, Finalizers cannot have generic type parameters on their own like the Generic method Exchange defined above with a type parameter T.

Categories: .NET Framework

CLR Generics – Constraints

October 22, 2006 1 comment
Generic Constraints
Generic type parameters can be constrained. Assume we want to write an encryption algorithm using a generic type.

public class EncryptionHelper {
...
}

Here we want all the type parameters to inherit from the System.IO.Stream class. How can this be done? Generic type parameters can be constrained. Assume we want to write an encryption algorithm using a generic type.

public class EncryptionHelper {
	public T Encrypt(T stream) {
		stream.Open(); // Error
	}
}

Error object class doesn’t have a Open method. Can this be a solution?

public class EncryptionHelper {
	public T Encrypt(T stream) {
		Stream streamType = (Stream)T; // Error
		...
	}
}

This will work.

public class EncryptionHelper {
	public T Encrypt(T stream) {
		Stream streamType = (Stream)((Object)T); 
		streamType.Open();
		...
	}
}

But what about the type safety which generics promised? The client can pass instance of any class to this method. The actual solution is to use constraints.

public class EncryptionHelper where T:System.IO.Stream {
	public T Encrypt(T stream) {
		stream.Open(); // Error
	}
}

The where clause is used to specify a constraint that the type parameter has to inherit from Stream class. The compiler can check for these calls. This is called a primary constraint. There are two special primary consraints ‘struct’, ‘class’ which specify whether the type argument has to be a value type or reference type. The primary constraint can specify at the most one non sealed type. This type cannot be an enum or a delegate. In addition using a constraint you also specify a zero or more interfaces a type parameter has to comply with. This is called a secondary constraint. In addition to primary and seondary constraints you can specify a type to have a default parameterless constructor. This is called a constructor constraint, specified like "…where T : new() …".

Categories: .NET Framework