Section 4.3. Anonymous Types and Object Initializers


4.3. Anonymous Types and Object Initializers

Consider the previous query to find the names of all doctors living in Chicago:

 var query = from d in doctors             where d.City == "Chicago"             select new { d.GivenFirstName, d.FamilyLastName }; 

The query interacts with complete Doctor objects from the doctors collection, but then projects only the doctor's first and last name. Look carefully at the syntax. We see the new keyword without a class name, and { } instead of ( ):

 new { d.GivenFirstName, d.FamilyLastName } 

The new operator is in fact instantiating an object, but the class is an anonymous typethe C# 3.0 compiler is automatically creating an appropriate class definition with a unique name and substituting that name. The only constructor provided by the generated class is a default one (i.e. parameter-less), which favors serialization but complicates the issue of object initialization. This is the motivation for the { }, which denote C# 3.0's new object initializer syntax. Object initializers provide an inline mechanism for initializing objects. And in the case of anonymous types, object initializers define both the data members of the type and their initial values.

For example, our earlier object instantiation is translated to

 new <Projection>f__12 { d.GivenFirstName, d.FamilyLastName } 

where the compiler has generated

 public sealed class <Projection>f__12 {        private string _GivenFirstName;        private string _FamilyLastName;        public string GivenFirstName        { get { return _GivenFirstName; } set { _GivenFirstName = value; } }        public string FamilyLastName        { get { return _FamilyLastName; } set { _FamilyLastName = value; } }        public <Projection>f__12( )              // default constructor: empty        { }        public override string ToString()        // dumps contents of all fields        { ... }        public override bool Equals(object obj)  // all fields must be Equals        { ... }        public override int GetHashCode()        { ... } } 

As you can see, the names and types of the properties are inferred from the initializers. If you prefer, you can assign your own names to the data members of the anonymous type. For example:

 new { First = d.GivenFirstName, Last = d.FamilyLastName } 

In this case the compiler generates:

 public sealed class <Projection>f__13 {        private string _First;        private string _Last;        public string First        { get { return _First; } set { _First = value; } }        public string Last        { get { return _Last; } set { _Last = value; } }        .        .        . } 

Anonymous types are being added to C# 3.0 primarily to support of LINQ, allowing developers to work with just the data they need in a familiar, object-oriented package. And courtesy of type inference, you can work with anonymous types in a safe, type-checked manner.

A current limitation of anonymous types is that they cannot be accessed outside the defining assemblywhat name would you use to refer to the class? In theory you could compile the code in a separate assembly and then use the generated name, but this is an obvious bad practice (and currently prevented by the fact that the generated name is invalid at the source code level). At issue is the design of N-tier applications, whose tiers communicate by passing data. If the data is packaged as an anonymous type, how do the other tiers refer to it? Since they cannot, anonymous types should be viewed as a technology for local use only.



LINQ[c] The Future of Data Access in C# 3. 0
LINQ[c] The Future of Data Access in C# 3. 0
ISBN: N/A
EAN: N/A
Year: 2006
Pages: 25

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net