I am a beginner who finally started understanding anonymous types.
(see old post What is the return type for a anonymous linq query select? What is the best way to send this data back?)
So in LINQ queries you form the type of return value you want within the linq query right? It seems the way to do this is anonymous type right?
Can someone explain to me if and when I could use a Tuple/Expando object instead?开发者_开发百科 They all seem very simliar?
Tuples and Expando objects are not normally used in LINQ. They're both quite different than anonymous types.
Anonymous types are commonly used to "shape" LINQ queries; for example, you can define a type that has a string Name
property and an int Age
property.
Tuples are types that only act as "pair" or "triplet" kinds of structures. For example a Tuple<string, int>
can be defined, but the names of the properties are named Item1
and Item2
, not Name
and Age
. Tuples are not normally used to shape LINQ queries because these property names make the code less clear.
ExpandoObject is totally different. It allows you to add properties at runtime to an existing object.
You don't state the context of your question, so I'll answer both LinqToObjects and LinqToSql.
In LinqToObjects, suppose you have a List<Customer> source
.
//Straight projection.
//no new instances are created when query is evaluated.
IEnumerable<Customer> result =
from c in source where c.Name == "Bob"
select c;
//Different Type projection
//a new instance of CustomerName is created
// for each element in the result when the query is evaluated.
IEnumerable<CustomerName> result =
from c in source where c.Name == "Bob"
select new CustomerName() {Name = c.Name};
//Anonymous Type Projection
//a new instance of an anonymous type is created
// for each element in the result when the query is evaluated.
//You don't have access to the type's name
// since the compiler names the type,
// so you must use var to talk about the type of the result.
var result =
from c in source where c.Name == "Bob"
select new {Name = "Bob"};
//Tuple Projection (same as Different Type Projection)
//a new instance of Tuple is created
// for each element in the result when the query is evaluated.
IEnumerable<Tuple<string, int>> result =
from c in source where c.Name == "Bob"
select new Tuple<string, int>(){First = c.Name, Second = c.Id};
In LinqToSql, suppose you have an IQueryable<Customer> db.Customers
//Straight projection
//when the query is resolved
// DataContext.Translate<Customer> is called
// which converts the private dbReader into new Customer instances.
IQueryable<Customer> result =
from c in db.Customers where c.Name == "Bob"
select c;
//Different Type Projection
//when the query is resolved
// DataContext.Translate<CustomerName> is called
// which converts the private dbReader into new CustomerName instances.
// 0 Customer instances are created.
IQueryable<Customer> result =
from c in db.Customers where c.Name == "Bob"
select new CustomerName() {Name = c.Name};
//Different Type Projection with a twist
//when the query is resolved
// DataContext.Translate<CustomerGroup> is called
// which converts the private dbReader into new CustomerGroup instances.
// 0 Customer instances are created.
//the anonymous type is used in the query translation
// yet no instances of the anonymous type are created.
IQueryable<Customer> result =
from c in db.Customers
group c by new {c.Name, TheCount = c.Orders.Count()} into g
select new CustomerGroup()
{
Name = g.Key.Name,
OrderCount = g.Key.TheCount,
NumberInGroup = g.Count()
};
Ok, that's enough for now.
精彩评论