instead of the generic type parameters (if any):
linkedlist<int,string> list = new linkedlist<int,string>();
type type = list.gettype();
methodinfo methodinfo = type.getmethod("addhead");
object[] args = {1,"aaa"};
methodinfo.invoke(list,args);
attributes and generics
when defining an attribute, you can instruct the compiler that the attribute should target generic type
parameters, using the new genericparameter value of the enum attributetargets:
[attributeusage(attributetargets.genericparameter)]
public class someattribute : attribute
{...}
note that c# 2.0 does not allow you to define generic attributes.
//does not compile:
public class someattribute<t> : attribute
{...}
yet internally, an attribute class can take advantage of generics by using generic types or define helper
generic methods, like any other type:
public class someattribute : attribute
{
void somemethod<t>(t t)
{...}
linkedlist<int,string> m_list = new linkedlist<int,string>();
}
generics and the .net framework
to conclude this article, here are how some other areas in .net besides c# itself are taking advantage of
or interacting with generics.
generic collections
the data structures in system.collections are all object-based, and thus inheriting the two problems
described at the beginning of this article, namely, poor performance and lack of type safety. .net 2.0
introduces a new set of generic collections in the system.collections.generics namespace. for example,
there are generic stack<t> and a generic queue<t> classes. the dictionary<k,t> data structure is
equivalent to the non-generic hashtable, and there is also a sorteddictionary<k,t> class somewhat
like sortedlist. the class list<t> is analogous to the non-generic arraylist. table 1 maps the new
types of system.collections.generics to those of system.collections.
table 1. mapping system.collections.generics to system.collections
system.collections.generics system.collections
comparer<t> comparer
dictionary<k,t> hashtable
list<t> arraylist
queue<t> queue
sorteddictionary<k,t> sortedlist
stack<t> stack
icollection<t> icollection
icomparable<t> system.icomparable
icomparer<t> icomparer
idictionary<k,t> idictionary
ienumerable<t> ienumerable
ienumerator<t> ienumerator
ikeycomparer<t> ikeycomparer
ilist<t> ilist
all the generic collections in system.collections.generics also implement the generic ienumerable<t>
interface, defined as:
public interface ienumerable<t>
{
ienumerator<t> getenumerator();
}
public interface ienumerator<t> : idisposable
{
t current{get;}
bool movenext();
}
briefly, ienumerable<t> provides access to the ienumerator<t> iterator interface, used for
abstracted iterations over the collection. all the collections implement ienumerable<t> on a nested
struct, where the generic type parameter t is the type the collection stores.
of particular interest is the way the dictionary collections define their iterators. a dictionary is actually a
collection of not one but two types of generic parameter—the key and the value.
system.collection.generics provides a generic struct called keyvaluepair<k,v> defined as:
struct keyvaluepair<k,v>
{
public keyvaluepair(k key,v value);
public k key(get;set;)
public v value(get;set;)
}
keyvaluepair<k,v> simply stores a pair of a generic key and a generic value, and in doing so, defines in
effect a new generic type. this new type is what the dictionary manages as a collection, and what it uses
for its implementation of ienumerable<t>. the dictionary class specifies the generic
keyvaluepair<k,v> structure as the item type for ienumerable<t> and icollection<t>:
public class dictionary<k,t> : ienumerable<keyvaluepair<k,t>>,
icollection<keyvaluepair<k,t>>,
//more interfaces
{...}
the key and value type parameters used in keyvaluepair<k,v> are of course the dictionary's own
generic key and value type parameters. i am calling this technique compound generics.
you can certainly take advantage of compound generics in your own generic data structures that use
pairs of keys and values. for example:
public class linkedlist<k,t> : ienumerable<keyvaluepair<k,t>> where k :
icomparable<k>
{...}
serialization and generics
.net allows you to have serializable generic types:
[serializable]
public class myclass<t>
{...}
when serializing a type, besides the state of the object members, .net persists metadata about the