The var keyword and anonymous types in C#

C#, like many object-oriented languages, enforces strong typing, which means that all variables and objects must be declared to be of a specific data type. Once declared, an object can be assigned only to objects of the correct type; any variance from this rule will not compile.

It might come as a bit of a surprise, then, that C# has what appears at first glance to be a keyword designed to avoid strong typing: the var keyword. As we’ll see, however, var does enforce strong typing, although in some cases it does allow you to work with objects without knowing explicitly what type they are.

Let’s start with the simplest way of using var: a straightforward variable declaration.

      var myString = "Var demo";
      Console.WriteLine("Type: " + myString.GetType());

Here, we’ve declared a string variable using var. The declaration works by inferring the data type of myString from the type of data which is assigned to it. The second line prints out this data type, which is System.String.

Since myString is a string variable, we cannot assign any other data type to it. For example, the following is an error:

    myString = 42;     // Wrong!

We can see from this that strong typing is in fact being enforced, even though we didn’t specify the data type explicitly in the declaration.

At this level, it might seem that there isn’t much point to using var, since if we know the data type of an object that we are declaring we might just as well say so in the declaration, rather than using a vague var declaration, which serves only to make the code harder for a human to follow.

This is true, and the var would, in practice, rarely be used in such situations. Var is much more useful when we create an anonymous typeAs its name implies, an anonymous type is a class without a name. The easiest way to understand it is just to show one in action:

      var comic = new {
        book = "Action Comics",
        title = "The Secrets of Superman's Fortress",
        year = 1970
      };
      Console.WriteLine(comic);
      Console.WriteLine("Type: " + comic.GetType());

In this example, we use the ‘new’ operator without any class name after it to create an object from an anonymous type. Within the braces, we specify three fields of this type: book, title and year.

In this case, the use of var to declare the object ‘comic’ is indispensable since we don’t have a name for the data type. The compiler does in fact generate a name for the anonymous type which we can see by calling GetType() as we do in the last line. This produces the output

Type: <>f__AnonymousType0`3[System.String,System.String,System.Int32]

The compiler-generated type isn’t exactly user-friendly, although we can see that it lists the data types of its constituent fields within the brackets.

If we print out the ‘comic’ object directly, as in the penultimate line above, we get

{ book = Action Comics, title = The Secrets of Superman's Fortress, year = 1970}

There are some important features of anonymous types that must be remembered. Probably the most important is that they are read-only. That is, although we can refer to the individual fields of comic by the usual dot notation, as in Console.Writeln(comic.book), we can’t assign any new values to any fields within comic, so the line below is wrong, even though we are assigning comic.year a value which is of the correct data type (int):

    comic.year = 1971;      // Wrong!

In the above example, we specified the data fields explicitly by naming each one and assigning it a specific value. We can also initialize an anonymous type by using other variables. So, with the above definitions we might say

      var anonObj2 = new
      {
        myString,
        comic
      };
      Console.WriteLine(anonObj2);

In this case, anonObj2 contains two fields, and the names of the fields are taken from the names of the variables used to intialize them, so its two fields are ‘myString’ and ‘comic’. The last line prints out:

{ myString = Var demo, comic = { book = Action Comics, title = The Secrets of Superman's Fortress, year = 1970 } }

This shows that one anonymous type can be used as a data field in a second anonymous type. To reference the ‘title’ field we use the usual dot notation of anonObj2.comic.title.

Visual Studio’s Intellisense is intelligent enough to work out an anonymous type’s fields as you are typing, so if you type anonObj2. the popup menu will show you the ‘myString’ and ‘comic’ data fields in its list. Hovering the mouse pointer over an anonymous object will show you a breakdown of the various fields it contains, so if you’re ever uncertain while programming that’s a quick way to determine what’s going on.

Although the programmer doesn’t have access to the compiler-generated name of an anonymous type, the compiler does keep track of the constituents of each object and, if two anonymous types contain the same data types in the same order, it will assign them the same internal type name. This is useful to know, since it then becomes possible to compare two such objects using the Equals() method. For example, we could write

      var comic = new {
        book = "Action Comics",
        title = "The Secrets of Superman's Fortress",
        year = 1970
      };

      var comic2 = new {
        book = "Action Comics",
        title = "The Secrets of Superman's Fortress",
        year = 1970
      };

      if (comic2.Equals(comic))
      {
        Console.WriteLine("Comics are equal");
      }

In this case, comic and comic2 are equal. Note a couple of things, however. First, remember that the equality operator == compares the references (essentially, the memory locations) of two objects and not their actual values. Thus if we’d said ‘if (comic2 == comic)’ above, the result would be false, since comic and comic2 are two different objects with different references.

Second, remember that the order in which the data fields are listed inside an anonymous object does matter (unlike in the definition of a named class). The Equals() method compares data fields one at a time in the order in which they are listed. Thus if we had written the following code instead, comic and comic2 would not be equal in any sense, even though the values of each of their named data fields are the same.

      var comic = new {
        book = "Action Comics",
        title = "The Secrets of Superman's Fortress",
        year = 1970
      };

      var comic2 = new {
        year = 1970,
        book = "Action Comics",
        title = "The Secrets of Superman's Fortress"
      };

      if (comic2.Equals(comic))  // false in this case
      {
        Console.WriteLine("Comics are equal");
      }

This behaviour in particular can be a common ‘gotcha’ since programmers are so used to ignoring the order in which data fields in a class are defined.

All of this is fine, but at this stage it might be less than obvious what use anonymous types are. Their main use is in the construction of queries using LINQ (Language INtegrated Query), which we’ll get to in a later post. However a few words about queries here might at least justify the existence of anonymous types.

A typical query will extract some information from a data source (which could be as simple as an array or as complex as an XML document or database) according to some selection criterion. Typically, the results of a query will consist of several data fields read from the data source, and the program won’t have a ready-made data type or class into which these data fields will fit. Since it is possible for a lot of queries to be done, each with a different collection of data as a result, it would be inconvenient to have to pre-define a special class for each query result. It is here that anonymous types save the day. But more on that when we start to take a look at LINQ.

Advertisements
Post a comment or leave a trackback: Trackback URL.

Trackbacks

  • […] be IEnumerable<PrimeMinisters>, but ‘var’ is a lot easier to type. Remember that ‘var’ creates a new object giving it the data type of whatever object is first assigned to […]

  • By JavaScript objects « Programming tutorials on October 22, 2012 at 4:24 PM

    […] JavaScript’s var is not the same as C#’s var. In C#, once a variable has been declared using var (or indeed, declared using any method), the […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: