I love C# 3.0 with its lambda expression, lazy evaluation, LINQ, anonymous types, etc. On the other hand you see in parts where they went silly (like the automatic property generator) or not far enough (no tuple as return method value)

Let me talk about the limitation of LINQ and its Anonymous type homie.
C# 3.0 does not allow var as a return type.

So there is no

public var GetCustomerLimitedContact()

Now LINQ is awesome, it allows you to do all crazy stuff of data projection, etc. The problem is, there is no good way to GET THOSE DATA PROJECTION OUT !!!

You are eiter stuck with some lame ass untyped DataTable or some throw away classes/structs just for this exact type of data projection. Or arrgh, you just pass your data control enabled to your method and bind it directly with LINQ out (shudder, horror !!!)

So you will be seeing a lot code like public DataTable GetCustomerLimitedContact(); or public List GetCustomerLimitedContact(); where CustomerLimitedContact is just a throw away class to handle a slice of customer query where you don't need to fill a full blown Customer object.

public class CustomerLimitedContact { public int Name; public int Email; }

Take a look at the following code and you will realize fully what I mean.

1
using System;
2 using System.Linq;
3 using System.Collections.Generic;
4 using System.Text;
5 using System.Data;
6 using System.Linq.Expressions;
7
8 namespace LinqConsole
9 {
10 class Program
11 {
12
13 static Customer[] _customers;
14 static Person[] _wives;
15
16 static void Main(string[] args)
17 {
18 Initialize();
19
20 DataTable customers = GetCustomerQuery();
21
22 Console.WriteLine("Customers");
23 foreach (DataRow r in customers.Rows)
24 {
25 Console.WriteLine(r["FirstName"] + " " + r["LastName"]);
26 }
27
28
29 Console.WriteLine();
30 Console.WriteLine();
31 Console.WriteLine("Parents");
32 var parents = GetHusbandAndWife();
33
34 foreach (var p in parents)
35 {
36 Console.WriteLine(p.Husband + " " + p.Wife);
37 }
38
39 Console.ReadLine();
40 }
41
42 public static void Initialize()
43 {
44 _customers = new Customer[]
45 {
46 new Customer{ FirstName = "Johny", LastName = "Dimas", WifeID = 1},
47 new Customer{ FirstName = "Adam", LastName = "John", WifeID = 2},
48 new Customer{ FirstName = "Johnton", LastName = "Bolton", WifeID = 0}
49 };
50
51 _wives = new Person[]
52 {
53 new Person { ID = 1, Name = "Jenny Miras"},
54 new Person { ID = 2, Name = "Imelda Marcos"}
55 };
56 }
57
58 public static DataTable GetCustomerQuery()
59 {
60 var cs = from c in _customers
61 select new { c.FirstName, c.LastName };
62
63 DataTable customers = new DataTable();
64 customers.Columns.Add("FirstName", typeof(string));
65 customers.Columns.Add("LastName", typeof(string));
66
67 foreach (var c in cs)
68 {
69 customers.Rows.Add(c.FirstName, c.LastName);
70 }
71
72 return customers;
73 }
74
75 public class Parents
76 {
77 public string Husband;
78 public string Wife;
79 }
80
81 public static List<Parents> GetHusbandAndWife()
82 {
83 var husbandAndWives = from c in _customers join w in _wives
84 on c.WifeID equals w.ID
85 select new { c.FirstName, c.LastName, w.Name };
86
87 var parents = new List<Parents>();
88 foreach (var h in husbandAndWives)
89 {
90
91 parents.Add(new Parents() { Husband = h.FirstName + " " + h.LastName, Wife = h.Name });
92 }
93
94 return parents;
95 }
96 }
97
98 public class Customer
99 {
100 public string FirstName { get; set; }
101 public string LastName { get; set; }
102 public int WifeID { get; set; }
103 }
104
105 public class Person
106 {
107 public int ID { get; set; }
108 public string Name { get; set; }
109 }
110 }

So, as you can see, the inability to return anonymous type in method
limits you in the data projection scenario where you just need to get out a
slice of data.