投影是指在将序列中的元素转换为一个自定义形式的操作。投影操作符Select和SelectMany用于选择出赋予了适当功能的值。SelectMany操作符可以处理多个集合。
LINQ表达式语法:
1. Select
Select操作符对单个序列或集合中的值进行投影。
1.1 原型定义
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector);
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, TResult> selector);
1.2 查询表达式
int[] fibonacci = new int[] { 1, 1, 2, 3, 5, 8, 13, 21 }; var result = from f in fibonacci select f; foreach (var item in result) { Console.WriteLine(item); }
IEnumerable<int> source = new int[] { 1, 1, 2, 3, 5, 8, 13, 21 }, filtered = source.Where(f => f > 5), sorted = filtered.OrderBy(f => f), query = sorted.Select(f => f * 2);
List<int> list = new List<int>() { 1, 2, 3, 4, 5 }; var query = from number in list where number < 3 select number;
3>. 扩展方法
int[] fibonacci = new int[] { 1, 1, 2, 3, 5, 8, 13, 21 }; var result = fibonacci.Select(f => f); foreach (var item in result) { Console.WriteLine(item); }
Object[] arr = new Object[] { "String", 12, true, 10.0m, 'a' }; var types = arr.Select(item => item.GetType().Name); foreach (var type in types) { Console.WriteLine(type); }
4>. 查询返回列
Select可以从序列中查询返回全部列、单独列及指定的多列。
返回单列:
using (NorthwindContext context = new NorthwindContext()) { var products = from p in context.Products select p.ProductName; }
var products = context.Products .Select(p => p.ProductName);
// using System.IO; DirectoryInfo di = new DirectoryInfo(@"D:\"); var query = from dir in di.GetDirectories() orderby dir.Name select dir.Name;
返回多列:
var products = from p in context.Products select new { p.ProductID, p.ProductName };
var products = context.Products .Select(p => new { p.ProductID, p.ProductName });
int[] fibonacci = new int[] { 1, 1, 2, 3, 5, 8, 13 }; var expr = fibonacci.Select((f, i) => new { Index = i, Number = f }); foreach (var item in expr) { Console.WriteLine(item.Index + "-" + item.Number); }
var expr = context.Products .OrderBy(p => p.ProductID) .Select(p => new ProductViewModel { ProductID = p.ProductID, ProductName = p.ProductName, UnitPrice = p.UnitPrice });
var expr = context.Products .Select(p => new { ProductID = p.ProductID, ProductName = p.ProductName, Available = p.UnitsInStock - p.UnitsOnOrder > 0 ? "In Stock" : "Out Of Stock" });
var expr = context.Products .Select(p => new { ProductID = p.ProductID, ProductName = p.ProductName, Units = new { p.UnitsInStock, p.UnitsOnOrder, Available = p.UnitsInStock - p.UnitsOnOrder > 0 ? "In Stock" : "Out Of Stock" } });
var query = context.Products .Select((p, index) => new { Position = index, p.ProductName, p.UnitPrice });
5>. Select方法实现
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector) { foreach (TSource element in source) { yield return selector(element); } }
2. SelectMany
SelectMany操作符可以将多个from字句组合起来,将每个对象的结果合并成一个序列。
1>. 原型定义
public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector);
public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector);
2>. 返回全部列
var expr = from c in context.Customers from o in c.Orders select o;
var expr = context.Customers .SelectMany(c => c.Orders);
3>. 返回指定列
var expr = from c in context.Customers from o in c.Orders select new { o.OrderID, o.OrderDate };
var expr = context.Customers .SelectMany(c => c.Orders .Select(o => new { o.OrderID, o.OrderDate }));
var query = context.Categories .Where(c => c.CategoryID == 1) .SelectMany(c => c.Products .Where(p => p.CategoryID == c.CategoryID) .Select(p => new { c.CategoryName, p.ProductName, p.UnitPrice }) );
var expr = from c in context.Categories from p in c.Products where c.CategoryName == "LINQ to Object" select p;
var query = from c in context.Categories select new { CategoryID = c.CategoryID, CategoryName = c.CategoryName, ProductIDs = from p in c.Products select p.ProductID };
var expr = from c in context.Categories from p in c.Products select new { c.CategoryName, p.ProductID, p.ProductName }; var expr = from c in context.Categories .SelectMany(c => from p in c.Products select new { c.CategoryName, p.ProductID, p.ProductName }) select c; var expr = context.Categories .SelectMany(c => c.Products .Select(p => new { c.CategoryName, p.ProductID, p.ProductName }));
3. Let
var expr = from p in context.Products let productInfo = p.UnitPrice + "," + p.UnitsInStock select new { p.ProductName, productInfo };
var expr = context.Products .Select(p => new { p, ProductInfo = p.UnitPrice + "," + p.UnitsInStock }) .Select(t => new { t.p.ProductName, t.ProductInfo }); foreach (var item in expr) { Console.WriteLine("{0}-{1}", item.ProductName, item.ProductInfo); }