A neat little type inference trick with C#

csharp-in-depth-coverI’m currently reading Jon Skeet’s book C# in Depth and enjoying it. This book is supposed to be fairly advanced and “aims to be a bridge between the existing introductory books and the language specification”. I think it does a great job at exactly that.

As I’ve worked almost exclusively with C# the last few years and done some funky stuff with generics, reflection etc. in various projects I haven’t really learned anything completely new but I’ve gained a much better understanding of how many of the language features that I often or more occasionally use work behind the scenes which is always good.

Another thing I enjoy with the book is that it’s riddled with various tricks and tips related to whatever feature is currently being described. However, when I stumble upon something that I find interesting but which is only useful on rare occasions I tend to forget it before I actually find myself in a situation where I could use it.

One such thing that I found particularly clever in it’s simplicity was a neat little trick related to type inference. Since I’m sure I won’t remember it the next time I need it I thought I’d blog it.

Generic type inference for methods but not for constructors

In C# we are able to use type inference (not specifying types explicitly but rather letting the compiler figure it out for us, thus often making our code more concise) in a number of situations. One of the most commonly used cases is when we call methods with generic type parameters. For instance, if we have a list of strings we can filter it using the Where method, like this:

var strings = new List<string> {"first", "second"};
strings.Where<string>(x => x.StartsWith("s"));

The above code does the job, returning all strings in the list starting with the letter s. However, specifying the type parameter for the Where method is redundant as the compiler can infer them from the parameters. In this specific case it does that from the first parameter which is the list itself since we’re dealing with an extension method. Thanks to the type inference capabilities of the compiler we can change the above code to be slightly more concise:

var strings = new List<string> {"first", "second"};
strings.Where(x => x.StartsWith("s"));

Type inference usually works well for methods but there’s no such support from the compiler when instantiating classes with type parameters. For instance, if we are creating a dictionary with strings as keys and integers as values we have to specify the type parameters explicitly.

new Dictionary<string, int>();

This is understandable. We’re not supplying any parameters or other type of information from which the compiler could deduce the types. But sometime, usually when we’re dealing with generic types that aren’t used for collections, we call constructors to which we have to supply instances of the types the class has as type parameters.

Utilizing type inference with factory methods

For instance, imagine we have the below class:

public static class Wrapper<T>
{
    public Wrapper(T wrapped)
    {
        Wrapped = wrapped;
    }

    public T Wrapped { get; set; }
}

To create an instance of this class we would have to call it’s constructor with an instance of whatever T is. We would also have to explicitly specify what T is, like this:

var wrappedInt = new Wrapper<int>(42);

In this case having to specify T explicitly seems redundant. After all we know that the type of 42 is integer. In this case specifying the type explicitly doesn’t obfuscate our code too much. But what if the class had two type parameters? Or seven? We’d have a list of type parameters that we’d have to break it up into several lines to fit it on the screen. In many situations this would be unfourtunate but beyond our control. But if the class also required instances of each type parameter in its constructor we could use a generic factory method in a non-generic version of the class, thereby allowing users of our API to leverage the type inference capabilities of the compiler. For the simple class above it could be implemented like this:

public class Wrapper
{
    public static Wrapper<T> Create<T>(T wrapped)
    {
        return new Wrapper<T>(wrapped);
    }
}

Anyone who needs an instance of the class can now create it without explicitly specifying the type parameter, as exemplified below.

var wrappedInt = Wrapper.Create(42);

We could also extend the non-generic class to have an extension method for object enabling us to create instances of the generic class by invoking the extension method on any object.

public static class Wrapper
{
    public static Wrapper<T> Create<T>(T wrapped)
    {
        return new Wrapper<T>(wrapped);
    }

    public static Wrapper<T> Wrap<T>(this T wrapped)
    {
        return Create(wrapped);
    }
}

Utilizing the extension method we could rewrite the previous call to the extension method to this:

var wrappedInt = 42.Wrap();

This might seem overkill and it probably is in most situations, but I found the trick rather thought-provoking in its simplicity.

PS. For updates about new posts, sites I find useful and the occasional rant you can follow me on Twitter. You are also most welcome to subscribe to the RSS-feed.

Comments

  1. Khaled Diab's avatar

    Khaled Diab 11 months ago

    A good post ..
    But I noticed that the Wrapper class is a static one, which is wrong :)

  2. Nelson's avatar

    Nelson 9 months ago

    This is the same concept used for .net 4's System.Tuple class(es). You can either

    var stuff = new Tuple(10, 10);


    Or,

    var stuff = Tuple.Create(10, 10);


    I've used this method myself almost always for cases in which every generic type argument is present in the constructor.
  3. Nelson's avatar

    Nelson 9 months ago

    Of course, HTML encoding bites me in the ass... my first code snippit should have been:

    var stuff = new Tuple<int, int>(10, 10);

Follow me on Twitter

  1. @tim_abell The gigantic ones are for customers who specifically ask for them only :) 1 months ago
  2. Looking to buy a gigantic easter egg filled with candy for delivery in Stockholm. Any recommendations? 1 months ago
  3. @strandberg_m Du måste skriva om resultatet efteråt! 1 months ago
follow me

Latest comments

  1. Joel Abrahamsson wrote "Hi Jonas! The fluent API is really geared towards working..." on Building a search page for an EPiServer site using Truffler
  2. Jonas wrote "Thank you for one more great write up! If you're not lucky ..." on Building a search page for an EPiServer site using Truffler
  3. David Knipe wrote "The CategoriesFacet method will save me a load of headaches ..." on Cool new features in the Truffler .NET API

About this site

This blog is built with EPiServer Community, EPiServer CMS, ASP.NET MVC and a bunch of other great products. The source code is available for download at the projects page, where you also can read more about this site and my other projects.

read more