Linq
Linq
所有常用用法汇总介绍整理,来自于 LINQ之路系列博客导航 - Life a Poem - 博客园 (cnblogs.com)
通用示例为
string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" };
-
Where:返回符合给定条件的elements子集(Where支持第二个可选参数为index位置)
var query = names.Where((n, i) => i % 2 == 0);
-
Take & Skip:返回开始的N个元素,忽略剩下的元素;忽略开始的N个元素,返回之后的元素
// 假设用户在一个图书数据库中查找包含"mercury"的所有图书 // 如果查找结果包含100条记录,下面的查询会返回前面20条 IQueryable<Book> query = dataContext.Books .Where(b => b.Title.Contains("mercury")) .OrderBy(b => b.Title) .Take(20); // 下面的查询则返回第21到40行数据(第2页) IQueryable<Book> query = dataContext.Books .Where(b => b.Title.Contains("mercury")) .OrderBy(b => b.Title) .Skip(20).Take(20); }
-
TakeWhile & SkipWhile:遍历输入,返回每一个元素,直到遇到一个不符合的,忽略剩下的;遍历输入,忽略每一个元素,直到遇到一个不符合的,返回剩下的
int[] numbers = { 3, 5, 2, 234, 4, 1 }; var takeWhileSmall = numbers.TakeWhile(n => n < 100); // { 3, 5, 2 } var skipWhileSmall = numbers.SkipWhile(n => n < 100); // { 234, 4, 1 }
-
Distinct:去除重复
char[] distinctLetters = "HelloWorld".Distinct().ToArray(); string s = new string(distinctLetters); // HeloWrd
-
Select: 转换每一个元素,个数一样
string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" }; IEnumerable<string> query = names .Select((s, i) => i + "=" + s); // { "0=Tom", "1=Dick", ... }
-
SelectMany:转换元素,个数不一样,多层Select
string[] fullNames = { "Anne Williams", "John Fred Smith", "Sue Green" }; IEnumerable<string> query = fullNames.SelectMany(name => name.Split()); foreach (string name in query) Console.Write(name + "|"); // Anne|Williams|John|Fred|Smith|Sue|Green|
-
OrderBy & OrderByDescending:升序排列;降序排列
-
ThenBy & ThenByDescending:前一次排序相同键值元素重新升序排列;降序排列
string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" }; //按姓名长度进行排序 IEnumerable<string> query = names.OrderBy(s => s.Length); // Result: { "Jay", "Tom", "Mary", "Dick", "Harry" }; //Jay和Tom、Mary和Dick,除非我们添加额外的ThenBy运算符 IEnumerable<string> query = names.OrderBy(s => s.Length).ThenBy(s => s); // Result: { "Jay", "Tom", "Dick", "Mary", "Harry" };
-
GroupBy:读取每一个元素,放入一个临时列表中,key相同的元素会被放入同一个子列表中
string[] files = Directory.GetFiles("c:\\temp"); IEnumerable<IGrouping<string, string>> query = files.GroupBy(file => Path.GetExtension(file)); foreach (IGrouping<string, string> grouping in query) { Console.WriteLine("Extension: " + grouping.Key); foreach (string filename in grouping) Console.WriteLine(" - " + filename); } // Result: Extension: .pdf - chapter03.pdf - chapter04.pdf Extension: .doc - todo.doc - menu.doc - Copy of menu.doc ...
-
First & FirstOrDefault:第一个元素
-
Last & LastOrDefault:最后一个元素
int[] numbers = { 1, 2, 3, 4, 5 }; int firstEven = numbers.First(n => n % 2 == 0); // 2 int lastEven = numbers.Last(n => n % 2 == 0); // 4 int firstBigError = numbers.First(n => n > 10); // Exception int firstBigNumber = numbers.FirstOrDefault(n => n > 10); // 0
-
ElementAt & ElementOrDefault:特定位置元素
int[] numbers = { 1, 2, 3, 4, 5 }; int third = numbers.ElementAt(2); // 3 int tenthError = numbers.ElementAt(9); // Exception int tenth = numbers.ElementAtOrDefault(9); // 0
-
Count & LongCount:返回元素个数;返回元素个数(64-bit整数)
-
Min & Max:返回最小元素;返回最大元素
-
Sum & Average:求和;求平均数
-
Contains:包含
-
Any:任意元素满足条件返回true
-
All:所有元素满足条件返回true
-
SequenceEqual:比较两个sequence,若他们拥有相同元素、相同顺序,返回true
-
Concat & Union:两个sequence所有元素;两个sequence所有元素,去重
int[] seq1 = { 1, 2, 3 }, seq2 = { 3, 4, 5 }; IEnumerable<int> concat = seq1.Concat(seq2); // { 1, 2, 3, 3, 4, 5 } IEnumerable<int> union = seq1.Union(seq2); // { 1, 2, 3, 4, 5 }
-
Intersect & Except:两个sequence都存在元素;第一个sequence有,第二个sequence没有的所有元素
int[] seq1 = { 1, 2, 3 }, seq2 = { 3, 4, 5 }; IEnumerable<int> commonality = seq1.Intersect(seq2), // { 3 } difference1 = seq1.Except(seq2), // { 1, 2 } difference2 = seq2.Except(seq1); // { 4, 5 }
-
Zip: 同步遍历两个sequence, 返回的sequence基于在每一个元素对上应用lambda表达式
int[] numbers = { 3, 5, 7 }; string[] words = { "three", "five", "seven", "ignored" }; IEnumerable<string> zip = numbers.Zip (words, (n, w) => n + "=" + w); // 产生的sequence包含如下元素 // 3=three // 5=five // 7=seven
-
OfType & Cast:接收一个非泛型集合,返回一个泛型集合,前者遇到不能转换的会忽略,后者会抛异常
DateTime offender = DateTime.Now; ArrayList classicList = new ArrayList(); // in System.Collections classicList.Add(offender); IEnumerable<int> sequence2 = classicList.OfType<int>(), // OK - ignores offending DateTime sequence3 = classicList.Cast<int>(); // Throws exception
-
ToArray & ToList & ToDictionary:
-
Repeat & Range:只能操作int整数,前者重复某个数值,后者是索引和元素个数
foreach (int i in Enumerable.Repeat(5, 3)) Console.Write(i + ""); // 5 5 5 foreach (int i in Enumerable.Range(5, 5)) Console.Write(i + ""); // 5 6 7 8 9
隐式类型变量 var
自动属性
简化定义字段和属性
注意:定义自动属性时,必须同时提供get
和set
关键字,所以不能定义只读或者只写的自动属性
class Person
{
private string firstName = string.Empty;
public string FirstName
{
get { return firstName; }
set { firstName = value; }
}
}
//-------------------------------------------------------
class Person
{
public string FirstName { get; set; }
}
匿名类型
相当于临时的自定义类,来封装一些数据
var data = new { Name = "Hello", Age = 1 };
Debug.LogFormat("{0},{1}", data.Name,data.Age);
匿名类型的相等语义,Equals
重写时基于值,==
重写时基于引用
static void AnonymousTypeEqualityTest()
{
// 构建两个匿名类型,拥有相同的名称/值对
var worker1 = new { FirstName = "Harry", SecondName = "Folwer", Level = 2 };
var worker2 = new { FirstName = "Harry", SecondName = "Folwer", Level = 2 };
// Equals测试
if (worker1.Equals(worker2))
Console.WriteLine("worker1 equals worker2");
else
Console.WriteLine("worker1 not equals worker2");
// ==测试
if (worker1 == worker2)
Console.WriteLine("worker1 == worker2");
else
Console.WriteLine("worker1 != worker2");
// Type Name测试
if (worker1.GetType().Name == worker2.GetType().Name)
Console.WriteLine("we are both the same type");
else
Console.WriteLine("we are different types");
}
拓展方法
Lambda表达式
对象初始化器
public class Point
{
public int X { get; set; }
public int Y { get; set; }
}
static void ObjectInitSyntax()
{
// 手动初始化各属性
Point aPoint = new Point();
aPoint.X = 10;
aPoint.Y = 20;
// 使用新的对象初始化语法进行初始化
Point bPoint = new Point { X = 10, Y = 20 };
}
查询运算符
string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" };
var list = names
.Where(n => n.Contains("a"))
.OrderBy(n => n.Length)
.Select(n => n.ToUpper());
foreach (string name in list) Debug.Log(name);
子查询
string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" };
// 获取所有长度最短的名字(注意:可能有多个)
IEnumerable<string> outQuery = names
.Where(n => n.Length == names
.OrderBy(n2 => n2.Length)
.Select(n2 => n2.Length).First()); // Tom, Jay"