var and Type Inference
var asks the compiler to read a local variable's type off the right-hand side; the type is still fixed at compile time.
var count = 10; // identical to: int count = 10;Writing the type twice in one line adds nothing: List<int> numbers = new List<int>(); says List<int> and then says it again. The keyword var asks the compiler to work the type out from the expression on the right of the =. That is type inference.
var count = 10; and int count = 10; are the same declaration. The compiler produces identical code for both. One is shorthand for the other, and you must be able to read either.
It is still one fixed type
var does not mean the variable can hold anything. The type is chosen once, when you build, and then never changes. After var label = "widgets"; the variable is a string forever, and assigning a number to it is a compile error. A variable whose type really is decided at run time is dynamic, a different keyword covered later.
Where var is allowed
var works only on local variables declared with a starting value, and on the variable of a foreach or using statement. It cannot be used for a field, a parameter or a return type. var x; and var x = null; do not compile, because neither gives the compiler a type to read.
The shorthand in the other direction
Since C# 9 you can keep the type on the left and shorten the right instead: List<int> numbers = new();. This is a target-typed new expression, and it saves the same repetition.
Example
// These two declarations are the same thing written two ways.
var count = 10;
int explicitCount = 10;
// var is not dynamic: the type is decided at compile time and then fixed.
var label = "widgets";
// label = 5; // does not compile: an int cannot go in a string variable
// GetType reports the real type the compiler chose.
Console.WriteLine(count.GetType());
Console.WriteLine(explicitCount.GetType());
Console.WriteLine(label.GetType());
// var saves repeating a long type name that is already on the right.
var numbers = new List<int>();
numbers.Add(count);
// The other shorthand, added in C# 9: keep the type, shorten the new.
List<int> alsoNumbers = new();
alsoNumbers.Add(explicitCount);
Console.WriteLine(numbers.Count + alsoNumbers.Count);
// Output:
// System.Int32
// System.Int32
// System.String
// 2When to use it
- Stop repeating a long generic type name on a declaration line
- Read someone else's code and work out the type from the right-hand side
- Declare a variable for a type that has no name you can write, such as an anonymous type
- Keep declarations short while the compiler still checks every assignment
More examples
var infers the nullable type
When the initial value is a reference type, var always infers the nullable form of it. That is documented behaviour, not a bug, and it quietly turns off the null warnings you probably wanted. Spell the type out when you are relying on the compiler to tell you a value can never be null.
// This project has <Nullable>enable</Nullable>, the default for dotnet new.
var inferred = "Ada"; // the compiler infers string?, not string
inferred = null; // no warning, because string? allows null
string declared = "Ada"; // plain string: null is not allowed
// declared = null; // the compiler warns here
Console.WriteLine(inferred is null);
// Output:
// TrueWhen the longhand reads better
The usual house rule is var where the right-hand side already names the type, and the explicit type where it does not. Nothing here is enforced by the compiler, so it is a review habit rather than a language rule.
// Clear: the type is sitting on the right of the =.
var customer = new Customer("Ada");
// Unclear: nothing on this line says what Load returns.
var data = Load();
// Better here: say the type, so a reader does not have to go and look.
Customer loaded = Load();
static Customer Load()
{
return new Customer("Grace");
}
class Customer
{
public string Name;
public Customer(string name)
{
Name = name;
}
}Types you cannot write out by hand
An anonymous type is created by new with a property list and no type name, so var is the only way to declare a variable for one. This is the one case where var is required rather than preferred; it turns up constantly in LINQ queries that select a few fields.
var point = new { X = 3, Y = 4 }; // an anonymous type: it has no name you can type
Console.WriteLine(point.X + point.Y);
// Output:
// 7
Discussion