The New Anonymous Types Feature in C# 3.0

At the PDC 2005, on the eve of the release of C# 2.0 (C# Whidbey), Microsoft previewed its plans for C# 3.0 (C# Orcas). Along with a list of fantastic new features such as Language Integrated Query (LINQ), Redmond also described a new feature called anonymous types. This article takes a deeper look at anonymous types.

Anonymous Types Defined

The C# 3.0 specifications describe anonymous types as tuple types automatically inferred and created from object initializers. Before you can fully understand the meaning of this definition, you need to understand the term "object initializer," which is the basis of the anonymous types feature.

An object initializer specifies values from one or more fields or properties of an object. That means you specify a set of properties for an object through a series of assignments, such as {a = 10, b = 20}, and an object is assigned these properties. In other words, an anonymous type is one that previously did not exist and was not defined explicitly in code.

Note: The compiler creates the anonymous type at compile time and not run time.

You can see this class in the disassembly through ILDASM (the IL Disassembler):

var p1 = new {Name = "A", Price = 3};

At compile time, the compiler creates a new (anonymous) type with properties inferred from the object initializer. Hence, the new type will have the properties Name and Price. The Get and Set methods, as well as the corresponding private variables to hold these properties, are generated automatically. At run time, an instance of this type is created and the properties of this instance are set to the values specified in the object initializer.

C# Internals

You might be surprised to learn that you define only the names of the properties and their values and C# 3.0 automatically creates a class from them. How does it do that? Check out how the compiler processes your request.

You started with the following line of code:

var p1 = new {Name = "A", Price = 3};

When the C# 3.0 compiler encounters a request such as this, it converts it in the background into a more verbose declaration, such as this:

class __Anonymous1
{
   private string name ;
   private int price;

   public string Name{ get { return name; } set { name = value ; } }
   public int Price{ get { return price; } set { price= value ; } }

}
__Anonymous1 p1 = new __Anonymous1();
p1.Name = "A";
pt.Price =3

Anonymous Types in Action

To get started, you need Visual Studio 2005 with .NET 2.0 installed. Next, you need to install the LINQ technology preview available for free download from MSDN.

If you have Visual Studio 2005 installed, you will have three new project templates titled LINQ Preview under Visual C#: LINQ Console Application, LINQ Windows Application, and LINQ Library.

To launch a project using anonymous types, take the following steps:

  1. Start the Visual Studio 2005 editor and create a new project, selecting LINQ Console as the project template in the New Project window.
  2. Name the project AnonTypes and click OK.
  3. Type the following code in the editor:
  4. // Program.cs
    using System;
    using System.Query;
    using System.Data.DLinq;
    
    namespace AnonTypes
    {
       class Program
       {
          static void Main(string[] args)
          {
             var p1 = new {Name = "A", Price = 3};
    
             Console.WriteLine("Name = {0}\nPrice = {1}",
                               p1.Name, p1.Price);
             Console.ReadLine();
          }
       }
    
    }
    
  5. Compile the application, which should compile correctly.
  6. Execute the application. It should print out the following:
  7. Name = A
    Price = 3
    

If you don't have Visual Studio 2005, you can still compile this application from the command line by typing the following:

C:\Program Files\LINQ Preview\Bin\Csc.exe
   /reference:"C:\Program Files\LINQ Preview\Bin\System.Data.DLinq.dll"
   /reference: System.dll
   /reference:"C:\Program Files\LINQ Preview\Bin\System.Query.dll"
   /out:AnonTypes.exe /target:exe Program.cs

Even though you have not explicitly defined a class in the code, the C# compiler automatically performs the following tasks:

  1. Deciphers the type.
  2. Creates a new class (that has the property's name and price).
  3. Uses this class to instantiate a new object.
  4. Assigns the object the parameters passed.

The New Anonymous Types Feature in C# 3.0

Delving Deep into the Code

To verify that the compiled assembly indeed creates a new class, start up ILDASM (located in C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin) and select the recently compiled assembly, AnonTypes.exe. Expand the tree-view, and you should see a view similar to Figure 1.

[Vipul1.jpg]

Figure 1. ILDASM Expanded Tree-view of AnonTypes

If you look carefully, ILDASM discloses information on how an anonymous type "<Projection>f__0" has been created. Along with the class, the private variables _Name (of the type string) and _Price (of the type 'int') have also been created. The Get and Set methods for both these variables also have been created, and they have the properties Name and Price.

Double-clicking any of the methods or variables reveals code that is very much like normal code. For example, when you click the Name property, you'll see the following code:

.property instance string Name()
{
   .get instance string AnonTypes.Program/
      '<Projection>f__0'::get_Name()
   .set instance void AnonTypes.Program/
      '<Projection>f__0'::set_Name(string)
}    // end of property '<Projection>f__0'::Name

Multiple Anonymous Types

If you have more than one anonymous type declared and their types are similar, the C# compiler is smart enough to detect that and produce only one class and create two instances of that class.

Suppose you have the following code (the newly added code is boldfaced):

using System;
using System.Query;

using System.Data.DLinq;

namespace AnonTypes
{
   class Program
   {
      static void Main(string[] args)
      {
         var p1 = new {Name = "A", Price = 3};
         var p2 = new {Name = "A", Price = 3};

         Console.WriteLine("Name = {0}\nPrice = {1}",
                           p1.Name, p1.Price);

         Console.ReadLine();
      }
   }

}

When you compile this code and open the assembly with ILDASM, the structure will like Figure 2.

[Vipul2.jpg]

Figure 2. Multiple Anonymous Types with Similar Declarations

As you can see, because the declarations were similar, C# created only one anonymous class, thus optimizing the code. If the declarations were not similar, you would have two anonymous classes.

If you modify the above code to look like the following (the changed code is boldfaced):

new {Name = "A", Price = 3};
var p2 = new {Name = "A"};

The C# compiler will create two different anonymous types because the types are different. Figure 3 shows the ILDASM representation.

[Vipul3.jpg]

Figure 3. Multiple Anonymous Types with Different Declarations

As you can see, C# has created two classes, <Projection>f__0 and <Projection>f__1.

Anonymous Types Without Explicit Class Structure Declaration

Anonymous types provide a mechanism for declaring anonymous types in your code without explicitly declaring the class structure. Additionally, the C# compiler is smart enough to optimize the creation of an anonymous type if one with a similar structure already exists.

About the Author

Vipul Patel is a Microsoft MVP (two years in a row) in Visual C#. He currently works at Microsoft through Volt Information Sciences, specializing in C# and deployment issues. Reach Vipul at Vipul_d_patel@hotmail.com.



About the Author

Vipul Vipul Patel

Vipul Patel is a Software Engineer currently working at Microsoft Corporation, working in the Office Communications Group and has worked in the .NET team earlier in the Base Class libraries and the Debugging and Profiling team. He can be reached at vipul_d_patel@hotmail.com

Downloads

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Stories about devastating cyberattacks are plaguing the news. Why? The DNS protocol is easy to exploit. See your network the way hackers do—as an easy target. Learn how you can effectively secure your DNS infrastructure today.

  • Packaged application development teams frequently operate with limited testing environments due to time and labor constraints. By virtualizing the entire application stack, packaged application development teams can deliver business results faster, at higher quality, and with lower risk.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds