Section 4.2. Type Inference


4.2. Type Inference

Interestingly, there is one very subtle difference between lambda expressions and anonymous methods: the latter require type information, while the former do not. Returning to our example, notice that the lambda expression

 d => d.City == "Chicago" 

does not specify a type for d. Without a type, the compiler cannot translate the lambda expression into the equivalent anonymous method:

 delegate(?????? d)  // what type is the argument d? {   return d.City == "Chicago"; } 

To make this work, C# 3.0 is actually inferring the type of d in the lambda expression, based on contextual information. For example, since doctors is of type List<Doctor>, the compiler can prove that in the context of calling FindAll

 doctors.FindAll(d => d.City == "Chicago") 

d must be of type Doctor.

Type inference is used throughout C# 3.0 to make LINQ more convenient, without any loss of safety or performance. The idea of type inference is that the compiler infers the types of your variables based on context, not programmer-supplied declarations. The compiler does this while continuing to enforce strict, compile-time type checking.

As we saw earlier when introducing LINQ, developers can take advantage of type inference by using the var keyword when declaring local variables. For example, the declarations

 var sum = 0; var avg = 0.0; var obj = new Doctor(...); 

trigger the inference of int for sum, double for avg, and Doctor for obj. The initializer in the declaration is used to drive the inference engine, and is required. The following are thus illegal:

 var obj2;          // ERROR: must have an initializer var obj3 = null;   // ERROR: must have a specific type 

Assuming the inference is successful, the inferred type becomes permanent and compilation proceeds as usual. Apparent misuses of the type are detected and reported by the compiler:

 var obj4 = "hi!"; . . . obj4.Close();  // Oops, wrong object! (ERROR: 'string' does not contain 'Close'). 

Do not confuse var with the concept of a VB variant (it's not), nor with the concept of var in dynamic languages like JavaScript (where var really means object). In these languages the variable's type can change, and so type checking is performed at runtimeincreased flexibility at the cost of safety. In C# 3.0 the type cannot change, and all type checking is done at compile-time. For example, if the inferred type is object (as for obj6 below), in C# 3.0 you end up with an object reference of very little functionality:

 object obj5 = "hi";  // obj5 references the string "hi!", but type is object var    obj6 = obj5;  // obj6 also references "hi!", with inferred type object . . . string s1 = obj6.ToUpper();  // ERROR: 'object' does not contain 'ToUpper' 

While developers will find type inference useful in isolation, the real motivation is LINQ. Type inference is critical to the success of LINQ since queries can yield complex results. LINQ would be far less attractive if developers had to explicitly type all aspects of their queries. In fact, specifying a type is sometimes impossible, e.g., when projections select new patterns of data:

             var query = from d in doctors             where d.City == "Chicago"             select new { d.GivenFirstName, d.FamilyLastName };  // type? foreach (var r in query)   System.Console.WriteLine("{0}, {1}", r.FamilyLastName, r.GivenFirstName); 

In these cases, typing is better left to the compiler.



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