我有这样的代码
var results = (from c in Customers join o in Orders on c.Id equals o.CustomerId join p in Products on p.Id equals o.ProductId select new { CustomerId = c.Id, // this is a GUID OrderId = o.Id, // this is a GUID ProductName = p.ProductName, }).ToList();假设我要获取订购名称为foo的产品的所有客户ID的列表 我的问题是,由于它是匿名类型,如何在要对结果运行的任何Linq查询中引用产品名称?
解决方案var filteredResults = results.Where(r => r.ProductName == "X");
编译器的类型推断将为您解决这个问题.您问题的完整答案:
var customerIds = results .Where(r => r.ProductName == "X") .Select(r => r.CustomerId) .Distinct() .ToList();或
var customerIds = (from r in results where r.ProductName == "X" select r.CustomerId) .Distinct() .ToList();编辑
关于类型推断的一些思考
要从称为list的字符串序列中选择长度,可以使用经典的静态方法语法或作为扩展方法来调用Select:
Enumerable.Select<string, int>(list, s => s.Length) list.Select<string, int>(s => s.Length)感谢类型推断,您不需要类型参数:
Enumerable.Select(list, s => s.Length) list.Select(s => s.Length)在这种情况下,编译器可以通过查看方法参数来证明类型参数是string和int,并且它代表您提供这些类型参数,而无需您将其键入源代码.
对于匿名类型,您不能提供第一个类型参数,因为该类型没有名称供您在源代码中使用(毕竟,匿名"是什么意思:没有名称"). (因此,您可以看到匿名类型和类型推断既是实现linq的关键条件,又是紧密相关的先决条件.)
如果您查看上述匿名类型示例的IL,则会看到编译器实际上为该类型指定了一个名称(其中包含在C#标识符中非法的字符).当您调用Select时,编译器从可枚举(IEnumerable<CrazilyNamedAnonymousType>)的类型推断出,第一个type参数应该是匿名类型,并且像字符串示例一样,它代表您提供该值.
I have code like this
var results = (from c in Customers join o in Orders on c.Id equals o.CustomerId join p in Products on p.Id equals o.ProductId select new { CustomerId = c.Id, // this is a GUID OrderId = o.Id, // this is a GUID ProductName = p.ProductName, }).ToList();Let's say I want to get a list of all customer Ids that orders a product that has name = foo My problem is that because its an anonymous type, how can I refer product name in any Linq query that I want to run on results?
解决方案 var filteredResults = results.Where(r => r.ProductName == "X");The compiler's type inference takes care of it for you. The complete answer to your question:
var customerIds = results .Where(r => r.ProductName == "X") .Select(r => r.CustomerId) .Distinct() .ToList();or
var customerIds = (from r in results where r.ProductName == "X" select r.CustomerId) .Distinct() .ToList();EDIT
Some musings on type inference
To select the lengths from a sequence of strings called list, you can call Select either using classic static method syntax or as an extension method:
Enumerable.Select<string, int>(list, s => s.Length) list.Select<string, int>(s => s.Length)Thanks to type inference, you don't need the type arguments:
Enumerable.Select(list, s => s.Length) list.Select(s => s.Length)In this case, the compiler can prove that the type arguments are string and int by looking at the method arguments, and it supplies these type arguments on your behalf without your having to type them into the source code.
For anonymous types, you can't provide the first type argument, because the type doesn't have a name for you to use in the source code (that's what "anonymous" means, after all: "without a name"). (You can see therefore that anonymous types and type inference were both critical -- and closely related -- prerequisites to implementing linq in the first place.)
If you check out the IL for the anonymous type example above, you'll see that the compiler has in fact given the type a name (which contains characters that are illegal in C# identifiers). When you call Select, the compiler deduces from the type of the enumerable (IEnumerable<CrazilyNamedAnonymousType>) that the first type argument should be the anonymous type, and, as with the string example, it supplies that value on your behalf.
更多推荐
如何从匿名类型引用项目
发布评论