Skip to main content

Cloud

Exploring C#: Type inference and the var keyword

Type inference is a language feature that isn’t very well-known, yet it is used by virtually every developer. It was formalized in the C# language with C# 3.0. Let’s start with an example of some code:
List<string> myList = new List<string>();
myList.Add<string>(“hello”);
The code isn’t too bad, but can be cleaned up:
var myList = new List<string>();
myList.Add(“hello”);
Functionally the code is identical, but more terse. The var keyword was introduced in C# 3.0. It is not a variant type. It is a static type, but it is not determined until the code is compiled. When the above code is compiled, the compiler sees that there is a variable called ‘myList’, and it knows that it should be of type List<string>. It knows this because it looks at what type is being assigned to the variable. You can not do the following:

var myList;
myList = new List<string>();
The reason is that since the variable is being created before it is being assigned, the compiler has no idea what type the variable should be. In order to use the var keyword, it must be initialized on the same line as it is declared.
If you want the variable to be of type IList<string>(), then you must specifically declare it that way; you can only use var if you want the variable type to be the same compile time type that is being assigned to it.
“Compile time” type is the key phrase, let’s say you’re invoking a method that has a return type of System.IO.Stream. If you store the results of the method call in a variable declared var, then that variable will be of type System.IO.Stream, because that is the type the compiler is aware of. If the method returns a MemoryStream at runtime, the variable type will still be Stream, since the type of var is determined at compile time, not at runtime.
These assumptions that the compiler is making on types is known as type inference.
Just because the var keyword is used doesn’t guarantee that your code is as simple as possible. I’ve actually seen the following line of code before:
var item = (IItem) new Item();
Item does implement the interface IItem, so there is nothing incorrect about the syntax, but it could actually be made more simplistic by removing the var keyword:
IItem item = new Item();
This isn’t type inference; it’s actually implicit type casting.
Lambdas as we know them would not be possible without type inference.
var lambda = x => x.Name
The above is not a valid statement. Why not? Because the compiler does not know what the type of “x => x.Name” is. It can either be used as a shorthand for expressing a function, or it could be shorthand for an expression.
Func<T,U> lambda = x => x.Name;
Expression<Func<T,U>> lambda = x => x.Name;
Both of the above are valid statements, but cause the compiler to behave in very different ways. With the first statement, the compiler creates a method, just like if you had wrote a method in your class. In the second statement, the compiler actually analyzes the expression and breaks it down into a series of nested objects that can be inspected at runtime and interoperate what the developer wants to do.
When you use a LINQ method such as Select, you would simply use the syntax x => x.Name. The reason you don’t need to specify the type, unlike before, is because of type inference. If the method you are invoking is looking for an expression, then the compiler infers that the syntax is for an expression, and compiles it as such. If the method you are invoking is expecting a function, then the compiler will compile it in that way. You also don’t need to specify what x is or what the return type of the expression is because of type inference. The compiler knows the type of x because the method signature dictates the type of x. You don’t need to specify the return type of the function/expression because the compiler sees that you are returning the Name property from x, so it assumes that is the return type.
Type inference is essentially there to make a bunch of safe assumptions about the types of various values in your code. Relying on the compiler to do this reduces the amount of code you have to write and makes your code much more readable. There is nothing stopping you from explicitly declaring all of your types, but it results in larger code files that aren’t as easy to read.

Thoughts on “Exploring C#: Type inference and the var keyword”

  1. Excellent overview of how var can be used to ease readability of code making it easier to maintain. I especially appreciated your covering the existence of scenarios where var does not make the code easier to read and likely should not be used. Like any other tool it should be leveraged only where it brings value as opposed to globally saying “always/never use var instead of explicit type declarations”. Thanks for the great post!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.