Chris Pietschmann

husband, father, hacker, entrepreneur, futurist, innovator, autodidact

NAVIGATION - SEARCH

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 variant types.

Straight from MSDN:
”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:

// traditional variable declarations in C#
// 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 a 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 is why the “var” keyword was introduced. Here are the same examples using the “var” keyword:

// variable declarations using "var" in C#
// 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 trivial, 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();

// "var" (easier to read)
var student = new Company.Namespace.People.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 these refactorings 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 Factory {
    public static Teacher GetPerson() {
        return new Teacher();
    }
}

Using the factory is straight forward, like this:

// use factory
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 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.

On a related note: Yes, 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";

 

Additional Reading

MSDN: var (C# Reference)
MSDN: Implicitly Typed Local Variables (C# Programming Guide)

blog comments powered by Disqus