What “var” really means in C# – It’s not “variant”

With the release of C# 3.0 came the addition (among many others) of the “var” keyword. I’ve seen MANY people confused about what this keyword is, does and means. Among these people with incorrect assumptions to the function of the “var” keyword, I have seen programmers/developers with varying amounts / years of experience. So, I’ve decided to write up a simple explanation; actually the same one I’ve told and/or emailed people over the last couple years.

var is not variant!

Since var is the beginning of the word variant, and especially since JavaScript uses var and is dynamically typed, it is easy to assume that var means variant. Although, it is important to remember that C# is a statically typed language; which leaves no room for a variant type.

Microsoft docs say : ”It is important to understand that the var keyword does not mean “variant” and does not indicate that the variable is loosely typed, or late-bound. It just means that the compiler determines and assigns the most appropriate type.”

The C# compiler wants to know what type a variable is so it can validate (at compile-time) all method calls and property accessors against the object that variable references.

It’s also important to remember that as var is not variant, neither does it mean dynamic. Variables declared using var are strongly typed.

What does “var” do?

It’s easier to think of var as a short-hand version of declaring your variables. Instead of defining what Type your variable is twice, you get to do it once with var.

Take the following traditional examples:

// using primitives
string name = "Chris";
int month = 3;

// using complex object
Person student = new Person();

The above declarations are fine; they work and are easy to read. However, why must we declare that name is a string, or month is an int, or student is a Person? Since we are assigning them an initial value on declaration, shouldn’t the compiler be able to tell what they they are implicitly?

Actually, YES!! That’s why the var keyword was introduced.

Here are the same examples using the var keyword:

// using primitives
var name = "Chris";
var month = 3;

// using complex object
var student = new Person();

Now, I must admit the use of var in the above primitive examples is rather simplistic, but it can save typing and reduce verbosity for complex object types; as in the student example. If you must include the full namespace of the complex object type or a longer object type name will help give you more benefit of using var.

// standard (verbose)
Company.Namespace.People.Person student = new Company.Namespace.People.Person();

// standard (verbose) with 'using'
using Company.Namespace.People;
Person student = new Person();

// with 'var' (easier to read)
var student = new Company.Namespace.People.Person();

// with 'var' (easier to read) with 'using'
using Company.Namespace.People;
var student = new Person();

As you can see in this example, using var makes the variable declaration easier to read. Remember that the compiler automatically replaces var with Company.Namespace.People.Person in the underlying MSIL that gets executed at runtime since it “knows” (based on the assignment) that student is Typed as a Person object.

Refactoring Types is Easier with var

When you change the return type of a method, you generally need to modify all the code that references that method. However, using “var” makes this refactoring a tiny bit simpler.

First, take the following IPerson interface and Factory that returns an instance of Teacher:

public class Teacher {
  public string Name { get; set; }
}

public class Student {
  public string Name { get; set; }
}

// a static factory
public static class Factory {
  public static Teacher GetPerson() {
    return new Teacher();
  }
}

Using the factory is straight forward, like this:

Teacher myPerson = Factory.GetPerson();

// set Name property
myPerson.Name = "John";

Now, imagine that we need to change our Factory.GetPerson method from returning a Teacher instance to returning a Student instance. The code would need to be changed to this:

// static factory changes to this
public static class Factory {
  public static Student GetPerson() {
    return new Student();
  }
}

// use factory
Student myPerson = Factory.GetPerson();

// set Name property
myPerson.Name = "John";

Now, if we had declared myPerson using the var keyword then the compiler would know that it’s a Teacher in the first example and then automatically know that the second example is now a Student. And since they both have a Name string property, then changing the return type of the Factory.GetPerson method would be all that is necessary and the compiler would automatically (via var) change the Typing of myPerson implicitly.

If the following example, you could change the return Type of Factory.GetPerson from Teacher to Student without needing to edit the usage code at all.

public class Teacher {
  public string Name { get; set; }
}

public class Student {
  public string Name { get; set; }
}

// a static factory
public static Factory {
  public static Student GetPerson() {
    // original
    // return new Teacher();

    // newly refactored return type
    return new Student();
  }
}

// usage code
// use factory
var myPerson = Factory.GetPerson();

// set Name property
myPerson.Name = "Steve";

The reason the compiler automatically handles this refactoring is that our usage of the myPerson variable (specifically the Name property) is identical between the two objects so the compiler is able to implicitly handle the changes made without requiring us to change additional code other than the return type of the factory method.

Related: It would generally be best practice to use an interface or base class in the above example, but I wrote it this way to demonstrate the capabilities of how var can make refactoring simpler. Also, using the above example where you start with a Teacher object and then change it to an IPerson interface instead of a Student object as shown will exhibit the same behavior and therefore utilize the same concept of easy refactoring.

For better visualization, here’s the above refactor example using an interface:

public interface IPerson {
  string Name { get; set; }
}

public class Teacher : IPerson {
  public string Name { get; set; }
}

public class Student : IPerson {
  public string Name { get; set; }
}

// a static factory
public static Factory {
  public static IPerson GetPerson() {
    // original
    // return new Teacher();

    // newly refactored return type
    return new Student();
  }
}

// Since "var" is used we can change
// Teacher to IPerson without needing to
// change this usage code.

// use factory
var myPerson = Factory.GetPerson();

// set Name property
myPerson.Name = "Steve";