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 aTeacher
object and then change it to anIPerson
interface instead of aStudent
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";
Related Posts
-
C#: Case-Insensitive String Contains Best Practices
18 Oct 2024 -
C#: Read Text and JSON File Contents into Variable in Memory
18 Jun 2024 -
How to Cast an Int to an Enum in C#
17 Jun 2024