I love C#. Jon Skeet's C# in Depth has given me even more reason for loving the language. A small example is a nice little way of not having to specify generic type parameters when creating objects of a type with type parameters.
I’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.
Similar articles
- Getting property and method names using static reflection in C#
- Inversion of Control – It’s broader than just injecting components
- Detecting mouse and keyboard input with .NET
- Learning Scala part five - Methods
- Learning Scala part three – Executing Scala code
- Syntax highlighting JSON with C#
- Learning Scala part four – Classes and Constructors
- C# method for cropping text without breaking words
Comments
comments powered by Disqus