h3mm3's blog

Stories from behind the keyboard

  • RSS
  • Twitter
Showing posts with label Generics. Show all posts
Showing posts with label Generics. Show all posts

Recently I needed to write some test against an utility class. This class handles an unmanaged type and of course I didn’t want to use this unmanaged type in my tests. I wrote an interface to target the only members of the unmanaged type that were used by my utility class. It turned out that this contract was really simple, having as its only member an indexer:

public interface IIndexable<T>    
{     
       object this[T fieldname] { get; set; }     
}

What I was not aware of (…shame on me…) is that you cannot cast a type to an arbitrary interface if the type doesn’t implement the interface. For instance, let’s consider Dictionary<string, object>. It’s indexer is declared as

public object this[string key] {get; set;} 

It looks like Dictionary<string, object> implements IIndexable<string>... True?

False. That would be duck-typing… Indeed Dictionary<string, object> *could* implement my new interface, but it doesn’t, since when it was defined, it didn't implement it.

Since a posteriori interface implementation is not possible, let’s see if you can define a cast operator, in order to convert a Dictionary to an IIndexable. Well, in C# defining a cast operator towards interfaces is denied. There’s no way to do this, and maybe for an handful of plausible reasons. The following code won’t ever compile (in other words, I cannot write any supplementary code in order to support the following line):

var indexme = (IIndexable<string>) new Dictionary<string, object>();

Since I couldn’t define any conversion method, I decided to implement a kind of proxy (I call it proxy for literal reasons, even if it resembles to me more like a tunnel). A class implements IIndexable<T> and is internally plumbed to the getter and the setter of the other class (e.g. the Dictionary), thanks to Reflection. Moreover, I wrote an extension method to easily create an instance of the proxy.

Let’s start from the extension method:

public static IIndexable<T> AsIndexable<T>(this object source)    
{     
    var t = source.GetType();     
    var idx = t.GetProperty(     
        "Item",     
        new Type[] {typeof (T)});

    var get = idx.GetGetMethod();    
    var set = idx.GetSetMethod();

    return new Indexable<T>(source, get, set);    
}   
As you can see, the extension method looks for the indexer –  t.GetProperty("Item", …) – and passes its getter and setter to the constructor of the proxy class (Indexable<T>). This class is defined like this:

public class Indexable<T> : IIndexable<T>    
{     
        public Indexable(object innerObject, MethodInfo get, MethodInfo set)     
        {     
            _innerObject = innerObject;     
            _get = get;     
            _set = set;     
        }     
        public readonly object _innerObject;     
        public readonly MethodInfo _get;     
        public readonly MethodInfo _set;     
        public object this[T property]     
        {     
            get     
            {     
                return _get.Invoke(_innerObject, new object[] {property });     
            }     
            set     
            {     
                _set.Invoke(_innerObject, new[] { property, value });     
            }     
        }     
    }

The hearth of the class is the indexer member. As you can see, its accessors invoke the accessors of the actual class, so you can simply use it like in the following example:

var dict = new Dictionary<string,object>();

dict.Add("foo", null); /* Allowing subsequent safe assignment operations,
like dict["foo"] = something */

var indexable = dict.AsIndexable();

Assert.IsNull(indexable["foo"]); 

indexable["foo"]="bar";

Assert.AreEquals("bar", indexable["foo"]); 

Writing such a proxy let my write a better decoupled code, since I managed to define my utility class methods as dependant to an interface (IIndexable<T>) instead of an unmanaged class. Perhaps this approach has to be unvestigated further, for instance against garbage collection issues.

I hope any reader comments about this soon. Happy programming!

C# generic type inference is a cool feature but you cannot use it at full power with anonymous types, without some hack. Lets see what I mean...

Could the compiler do more?

One useful feature about C# generics is the ability of the compiler to recognize (precisely to infer) the type of the type parameter(s) when you invoke a generic method, based on the type of the corresponding input parameter(s).

For instance, let's consider the following class:

class ClassA
{
  public void Method<T>(T input)
  {
    //Use input in some way...
    Console.Write(input);
  }
}

You can call ClassA.Method() in this way:

Method<T>("Hello generics!");

…or without specifing the value of the T parameter:

Method("Hello generic type inference!");

This feature is most useful when you work with anonymous types, since anonymity deprives you the ability to specify the type name:

var something = new {Text="Hello generics", CanInfer=true};
MethodOne(something);

Type inference in generic classes

Unfortunately, generic type inference is not allowed during constructor invocations because the value of the type parameter is part of the definition of the class you want to instanciate. For instance, let's declare a generic class:

class ClassB<T> {  
  public ClassB(T input) {
    _Input = input; 
  }

  private readonly T _Input; 

  public Method {
    //This will use the _Input field in some way…
  } 
}

In order to instanciate ClassB<T> you have to pass an input type parameter to the constructor, like this:

var c = new ClassB<string>("Hello generics!");

c.MethodOne();

Even if the constructor gets an input parameter of type T, you are not allowed to invoke the constructor without passing explicitly the generic type. For instance, the following invocation will produce a compilation error:

var a = new {Text="Hello generics", CanInfer=false};
var c = new ClassB(a); //This line wont compile

Here comes the hack

There are situations when the lack of generic type inference for generic classes is critical. The previous example is one of them: it looks like you cannot use ClassB<T> with anonymous types at all!

Luckily you can achieve generic type inference …with a little hack! Sorriso All you need is to define a non-generic version ClassB of your generic class ClassB<T> and to implement a generic factory method like this:

static class ClassB
{
  public static ClassB<T> GetInstance<T>(T input)
  {
    return new ClassB<T>(input);
  }
}

Now you can use generic type inference at full power!

var a = new {Text="Can you infer my type?", CanInfer=true};

//Look ma, no generic type parameter!
var cba = ClassB.GetInstance(a);
cba.Method();

Enjoy.