New in C# 3.0: Create and Initialize Collection Objects in One Step

To recap a previous article, the new object initializer feature in C# 3.0 is a simple syntax that eases the construction and initialization of objects. Suppose you have a class, Student, that looks like this:

public class Student
{
   public string firstName;
   public string lastName;
}

You can create an object of this class by using object initializers as follows:

var student1 = new Student{firstName = "Bruce", lastName = "Willis"};

C# 3.0's new collection initializers operate in a similar manner. Any object that implements System.Collections.Generic.ICollection<T> can have its values initialized with a collection initializer.

A collection initializer is made up of the following:

  • A sequence of object initializers, enclosed by "{" and "}" tokens and separated by commas.
  • Element initializers, each of which specifies an element to be added to the collection object being added. (Element initializers cannot be assignment expressions in a collection initializer.)

How does it work? A collection initializer must observe the following rules:

  • The collection object to which a collection initializer is applied must be of a type that implements System.Collections.Generic.ICollection<T> for exactly one T.
  • An implicit conversion from the type of each element initializer to T must exist. A collection initializer invokes the ICollection<T>.Add(T) method for each specified element in order.

As an example, the following collection initializer creates and initializes a new collection of strings with three members "Alice", "Bob", and "Chris":

List<string> names = new List<string> { "Alice", "Bob", "Chris" };
Note: All the initialization values are of type string. Otherwise, you'd get a compiler error.

Collection Initializers in Action

Suppose you want to represent a class and its enrolled students. You can do this through collection initializers by using C# 3.0 code such as the following:

using System;
using System.Collections.Generic;
using System.Text;
using System.Query;
using System.Xml.XLinq;
using System.Data.DLinq;

namespace CollectionInitializer
{
   class Program
   {
      public class MyClass
      {
         public string nameofClass;
         public List<string> studentNames = new List<string>();
      }
      static void Main(string[] args)
      {
         var classes = new List<MyClass>
         {
            new MyClass
            {
               nameofClass = "Science",
               studentNames = {"Laura", "George"}
            },
            new MyClass
            {
               nameofClass = "Commerce",
               studentNames = {"Bill", "Hillary"}
            }
         };
      }
   }
}

If you have Visual Studio 2005 (any flavor) and the LINQ Preview installed, you can compile the above code in the IDE.

If you do not have VS 2005 but have the LINQ Preview installed, you can use the following command to compile the code from the command line:

C:\Program Files\LINQ Preview\Bin\Csc.exe
/reference:"C:\Program Files\LINQ Preview\Bin\System.Data.DLinq.dll"
/reference:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.Data.dll
/reference:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.dll
/reference:"C:\Program Files\LINQ Preview\Bin\System.Query.dll"
/reference:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.Xml.dll
/reference:"C:\Program Files\LINQ Preview\Bin\System.Xml.XLinq.dll" Program.cs

Code Internals

Take a closer look at this snippet from the preceding C# 3.0 code:

var classes = new List<MyClass>
{
   new MyClass
   {
      nameofClass = "Science",
      studentNames = {"Laura", "George"}
   },
   new MyClass
   {
      nameofClass = "Commerce",
      studentNames = {"Bill", "Hillary"}
   }
};

To the compiler, it has the same effect as the following:

var classes = new List<MyClass>();
var __c1 = new MyClass ();
__c1.nameofClass = "Science";
__c1.studentNames.Add("Laura");
__c1.studentNames.Add("George");
classes.Add(__c1);
var __c2 = new MyClass();
__c2.nameofClass = "Commerce";
__c2.studentNames.Add("Bill");

__c2.studentNames.Add("Hillary");

classes.Add(__c2);

If you fire up ILDASM and open the compiled binary, you will see something similar to Figure 1.

Figure 1: Compiled Binary of Sample Code Snippet

New in C# 3.0: Create and Initialize Collection Objects in One Step

If you double-click the Main node in ILDASM, you will see the following code:

.method private hidebysig static void  Main(string[] args) cil managed
{
   .entrypoint
   // Code size       138 (0x8a)
   .maxstack  3
   .locals init ([0] class [mscorlib]System.Collections.Generic.List`1
                     <class CollectionInitializer.Program/MyClass>
                     classes,
                 [1] class [mscorlib]System.Collections.Generic.List`1
                     <class CollectionInitializer.Program/MyClass>
                     '<tampa>f__0',
                 [2] class CollectionInitializer.Program/MyClass
                     '<tampa>f__1',
                 [3] class CollectionInitializer.Program/MyClass
                     '<tampa>f__2')
   IL_0000:  nop
   IL_0001:  nop
   IL_0002:  newobj     instance void class [mscorlib]System.Collections.
                        Generic.List`1<class CollectionInitializer.
                        Program/MyClass>::.ctor()
   IL_0007:  stloc.1
   IL_0008:  ldloc.1
   IL_0009:  nop
   IL_000a:  newobj     instance void CollectionInitializer.
                        Program/MyClass::.ctor()
   IL_000f:  stloc.2
   IL_0010:  ldloc.2
   IL_0011:  ldstr      "Science"
   IL_0016:  stfld      string CollectionInitializer.
                        Program/MyClass::nameofClass
   IL_001b:  nop
   IL_001c:  ldloc.2
   IL_001d:  ldfld      class [mscorlib]System.Collections.Generic.List`1
                        <string> CollectionInitializer.
                        Program/MyClass::studentNames
   IL_0022:  ldstr      "Laura"
   IL_0027:  callvirt   instance void class [mscorlib]System.
                        Collections.Generic.List`1<string>::Add(!0)
   IL_002c:  nop
   IL_002d:  ldloc.2
   IL_002e:  ldfld      class [mscorlib]System.Collections.Generic.List`1
                        <string> CollectionInitializer.
                        Program/MyClass::studentNames
   IL_0033:  ldstr      "George"
   IL_0038:  callvirt   instance void class [mscorlib]System.Collections.
                        Generic.List`1<string>::Add(!0)
   IL_003d:  nop
   IL_003e:  nop
   IL_003f:  ldloc.2
   IL_0040:  nop
   IL_0041:  callvirt   instance void class [mscorlib]System.Collections.
                        Generic.List`1<class CollectionInitializer.
                        Program/MyClass>::Add(!0)
   IL_0046:  nop
   IL_0047:  ldloc.1
   IL_0048:  nop
   IL_0049:  newobj     instance void CollectionInitializer.
                        Program/MyClass::.ctor()
   IL_004e:  stloc.3
   IL_004f:  ldloc.3
   IL_0050:  ldstr      "Commerce"
   IL_0055:  stfld      string CollectionInitializer.
                        Program/MyClass::nameofClass
   IL_005a:  nop
   IL_005b:  ldloc.3
   IL_005c:  ldfld      class [mscorlib]System.Collections.Generic.List`1
                        <string> CollectionInitializer.
                        Program/MyClass::studentNames
   IL_0061:  ldstr      "Bill"
   IL_0066:  callvirt   instance void class [mscorlib]System.Collections.
                        Generic.List`1<string>::Add(!0)
   IL_006b:  nop
   IL_006c:  ldloc.3
   IL_006d:  ldfld      class [mscorlib]System.Collections.Generic.List`1
                        <string> CollectionInitializer.
                        Program/MyClass::studentNames
   IL_0072:  ldstr      "Hillary"
   IL_0077:  callvirt   instance void class [mscorlib]System.Collections.
                        Generic.List`1<string>::Add(!0)
   IL_007c:  nop
   IL_007d:  nop
   IL_007e:  ldloc.3
   IL_007f:  nop
   IL_0080:  callvirt   instance void class [mscorlib]System.Collections.
                        Generic.List`1<class CollectionInitializer.
                        Program/MyClass>::Add(!0)
   IL_0085:  nop
   IL_0086:  ldloc.1
   IL_0087:  nop
   IL_0088:  stloc.0
   IL_0089:  ret
}    // end of method Program::Main

As you can see from the two snippets prior to the above, C# 3.0 presents a significant improvement in language syntax.

One-Step Creation and Initialization for Object Collections

Collection initializers, one of the new features of C# 3.0, provide a new syntax to initialize collection objects. This simple syntax combines collection object creation and initialization into a single step.

About the Author

Vipul Patel was a Microsoft MVP for two years. He specializes in C# and deployment issues. You can reach him 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

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • With the average hard drive now averaging one terabyte in size, the fallout from the explosion of user-created data has become an overwhelming volume of potential evidence that law-enforcement and corporate investigators spend countless hours examining. Join Us and SANS' Rob Lee for our 45-minute webinar, A Triage and Collection Strategy for Time-Sensitive Investigations, will demonstrate how to: Identify the folders and files that often contain key insights Reduce the time spent sifting through content by …

Most Popular Programming Stories

More for Developers

RSS Feeds