deft flux

A portal into the creative workings of David Meyer

About the author

David Meyer (a.k.a. "deft flux") is a software developer fluent in C#, C++, Java and others. He also programs in his spare time and enjoys playing instruments and making electronic music.
E-mail me Send mail

Recent posts

Recent comments

Authors

Disclaimer

The opinions expressed by the author are his alone and do not represent any other person or organization unless stated otherwise. The opinions given in comments are solely those of the person who wrote the comment and are not necessarily the opinions of the author of this site. The author of a post is not responsible for the content of its comments.

© Copyright 2008
David Meyer

Trick to refer to objects of generic types

I realized something while I was working on a project.  I thought it might be a useful idea, so I thought I'd write a post.

To help clarify the following, I will be using the terminology for generics as it appears in System.Reflection.  List<T> is an example of a "generic type definition", because its type arguments have not been specified.  Whereas List<string> is a "generic type".  T is a "type parameter" and string is a "type argument".

In .NET (C#), while a generic type definition can be referenced using typeof (e.g. typeof(List<>)) in order to get a Type object, you cannot declare a variable with a generic type definition type.  This is because the generic type definition isn't really a type in .NET, it's more of a template for a type.  Furthermore, generic types from the same definition do not automatically inherit from a common base class.  This presents a problem when you want to be able to reference an object of a generic type without knowing its type arguments.

I ran into this problem yesterday.  I realized, however, that since types can be distinguished by how many type parameters they have, a type that is not generic and a generic type definition with one or more type arguments can both be defined without causing a naming conflict.  This can commonly be seen with the old System.Collections classes and interfaces and the new generic System.Collection.Generic types (e.g. Stack vs. Stack<T>).

So I performed a little trick taking advantage of this in order to solve the above problem.  Here's some example code:

public abstract class TransactionField
{
    
}

public class TransactionField<T> : TransactionField
{
    private T m_Value;
    
    public T Value { get { return m_Value; } set { m_Value = value; } }
}
 

Now an object of any TransactionField<T> type can be referenced as simply TransactionField.  This is great for referencing, but what about that Value property?  What if you need to be able to access that property for any TransactionField<T> object?  Check this out:

public abstract class TransactionField
{
    public object Value { get { return _Value; } set { _Value = value; } }
    
    protected abstract object _Value { getset; }
}

public class TransactionField<T> : TransactionField
{
    private T m_Value;
    
    public new T Value { get { return m_Value; } set { m_Value = value; } }
    
    protected override object _Value { get { return Value; } set { Value = (T)value; } }
}
 

It gets a little confusing with the naming.  But basically, TransactionField defines an protected abstract property _Value so that it can access the value stored in types derived from it.  It also defines a public property Value which provides public access to the value stored in the derived type via _Value.  Finally, TransactionField<T> defines a new property with the same name Value except this one uses the type argument instead of object.  

Now at this point, you might be wondering what the point of using generics at all in this scenario is.  Well, TransactionField<T> replaces the Value property with a typesafe one.  When you deal with the generic type, you won't need to cast any values.  This approach is the best of both worlds.  The object can be dealt with as an object of a generic type or a non-generic type, depending on what is needed for the code that is using the object.

Currently rated 4.0 by 4 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Development
Posted by deftflux on Thursday, October 11, 2007 5:45 PM
Permalink | Comments (1) | Post RSSRSS comment feed

Related posts

Comments

Avi Shilon il

Wednesday, April 16, 2008 4:33 AM

Gravatar

Too much trouble just to get simple inheritance working!
I think that this design by Microsoft is flawed (that is, if it's by design and not some sort of CLR limitation).
And this is just a simple example. Imgaine what one should do in order to get inheritance with generics in a
real application. Not an encouraging thought...
Thanks anyway David,

Avi

Add comment


(Will show your Gravatar icon)  

  Country flag




Live preview

Thursday, August 21, 2008 2:57 AM

Gravatar