LINQ基础(一)
LINQ(Language Integrated Query,语言集成查询),在C#语言中集成了查询语法,可以用相同的语法访问不同的数据源。
LINQ提供了不同数据源的抽象层,所以可以使用相同的语法。
这里主要介绍LINQ的核心原理和C#中支持C# LINQ查询的语言扩展。
1.语法
使用LINQ查询出来自巴西的所以世界冠军。这里可以使用List<T>类的FindAll()方法,但使用LINQ查询语法更简单
static void LINQQuery() { // var query = from r in Formula1.GetChampions() where r.Country == "Brazil" orderby r.Wins descending select r; foreach (var r in query) { Console.WriteLine("{0:A}", r); } }
变量query只指定了LINQ查询。该查询不是通过这个赋值语句执行的,而是使用foreach循环访问查询时执行的。
2.扩展方法
编译器会转换LINQ查询,以调用方法而不是LINQ查询。LINQ为IEnumerable<T>接口提供了各种扩展方法(扩展方法在http://www.cnblogs.com/afei-24/p/6703843.html介绍到),以便用户在实现了该接口的任意集合上使用LINQ查询。
定义LINQ扩展方法的一个类是System.Linq名称空间中的Enumerable。只需要导入这个名称空间,就打开了这个类的扩展方法的作用域。下面是Where()扩展方法的实现代码:
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source,Func<TSource,bool> predicate) { foreach(TSource item in source) { if(predicate(item)) { yield return item; } } }
因为Where()作为一个泛型方法,所以它可以用于包含在集合中的任意类型。实现了IEnumerable<T>接口的任意集合都支持它。
3.推迟查询的执行
前面提到,在运行期间定义LINQ查询表达式时,查询不会运行。查询在迭代数据项时才会运行。
举个例子:
static void DeferredQuery() { var names = new List<string> { "Nino", "Alberto", "Juan", "Mike", "Phil" }; var namesWithJ = from n in names where n.StartsWith("J") orderby n select n; Console.WriteLine("First iteration"); foreach (string name in namesWithJ) { Console.WriteLine(name); } Console.WriteLine(); names.Add("John"); names.Add("Jim"); names.Add("Jack"); names.Add("Denny"); Console.WriteLine("Second iteration"); foreach (string name in namesWithJ) { Console.WriteLine(name); } }
输出:
因为查询在迭代时才执行,所以在第一次输出后有添加项再输出,会显示又添加的项。
但在调用方法ToArray(),ToList等方法时,不会延迟执行:
static void NotDeferredQuery() { var names = new List<string> { "Nino", "Alberto", "Juan", "Mike", "Phil" }; var namesWithJ = (from n in names where n.StartsWith("J") orderby n select n).ToList(); Console.WriteLine("First iteration"); foreach (string name in namesWithJ) { Console.WriteLine(name); } Console.WriteLine(); names.Add("John"); names.Add("Jim"); names.Add("Jack"); names.Add("Denny"); Console.WriteLine("Second iteration"); foreach (string name in namesWithJ) { Console.WriteLine(name); } }
输出:
下面是用到的类,后续的也需要用到这些代码。
//这个类创建需要的列表 public static class Formula1 { private static List<Racer> racers; //返回一组赛车手 public static IList<Racer> GetChampions() { if (racers == null) { racers = new List<Racer>(40); racers.Add(new Racer("Nino", "Farina", "Italy", 33, 5,
new int[] { 1950 }, new string[] { "Alfa Romeo" })); racers.Add(new Racer("Alberto", "Ascari", "Italy", 32, 10,
new int[] { 1952, 1953 }, new string[] { "Ferrari" })); racers.Add(new Racer("Juan Manuel", "Fangio", "Argentina", 51, 24,
new int[] { 1951, 1954, 1955, 1956, 1957 }, new string[] { "Alfa Romeo", "Maserati", "Mercedes", "Ferrari" })); racers.Add(new Racer("Mike", "Hawthorn", "UK", 45, 3,
new int[] { 1958 }, new string[] { "Ferrari" })); racers.Add(new Racer("Phil", "Hill", "USA", 48, 3,
new int[] { 1961 }, new string[] { "Ferrari" })); racers.Add(new Racer("John", "Surtees", "UK", 111, 6,
new int[] { 1964 }, new string[] { "Ferrari" })); racers.Add(new Racer("Jim", "Clark", "UK", 72, 25,
new int[] { 1963, 1965 }, new string[] { "Lotus" })); racers.Add(new Racer("Jack", "Brabham", "Australia", 125, 14,
new int[] { 1959, 1960, 1966 }, new string[] { "Cooper", "Brabham" })); racers.Add(new Racer("Denny", "Hulme", "New Zealand", 112, 8,
new int[] { 1967 }, new string[] { "Brabham" })); } return racers; } private static List<Team> teams; //返回一组冠军车队 public static IList<Team> GetContructorChampions() { if (teams == null) { teams = new List<Team>() { new Team("Vanwall", 1958), new Team("Cooper", 1959, 1960), new Team("Ferrari", 1961, 1964, 1975, 1976, 1977, 1979, 1982, 1983, 1999,
2000, 2001, 2002, 2003, 2004, 2007, 2008), new Team("BRM", 1962), new Team("Lotus", 1963, 1965, 1968, 1970, 1972, 1973, 1978), new Team("Brabham", 1966, 1967), new Team("Matra", 1969), new Team("Tyrrell", 1971), new Team("McLaren", 1974, 1984, 1985, 1988, 1989, 1990, 1991, 1998), new Team("Williams", 1980, 1981, 1986, 1987, 1992, 1993, 1994, 1996, 1997), new Team("Benetton", 1995), new Team("Renault", 2005, 2006 ), new Team("Brawn GP", 2009), new Team("Red Bull Racing", 2010, 2011) }; } return teams; } private static List<Championship> championships; //返回GetChampionships类型的集合 public static IEnumerable<Championship> GetChampionships() { if (championships == null) { championships = new List<Championship>(); championships.Add(new Championship { Year = 1950, First = "Nino Farina", Second = "Juan Manuel Fangio", Third = "Luigi Fagioli" }); championships.Add(new Championship { Year = 1951, First = "Juan Manuel Fangio", Second = "Alberto Ascari", Third = "Froilan Gonzalez" }); championships.Add(new Championship { Year = 1952, First = "Alberto Ascari", Second = "Nino Farina", Third = "Piero Taruffi" }); championships.Add(new Championship { Year = 1953, First = "Alberto Ascari", Second = "Juan Manuel Fangio", Third = "Nino Farina" }); championships.Add(new Championship { Year = 1954, First = "Juan Manuel Fangio", Second = "Froilan Gonzalez", Third = "Mike Hawthorn" }); championships.Add(new Championship { Year = 1955, First = "Juan Manuel Fangio", Second = "Stirling Moss", Third = "Eugenio Castellotti" }); championships.Add(new Championship { Year = 1956, First = "Juan Manuel Fangio", Second = "Stirling Moss", Third = "Peter Collins" }); } return championships; } }
//车手类 [Serializable] public class Racer : IComparable<Racer>, IFormattable { public Racer(string firstName, string lastName, string country, int starts, int wins) : this(firstName, lastName, country, starts, wins, null, null) { } public Racer(string firstName, string lastName, string country, int starts,
int wins, IEnumerable<int> years, IEnumerable<string> cars) { this.FirstName = firstName; this.LastName = lastName; this.Country = country; this.Starts = starts; this.Wins = wins; this.Years = new List<int>(years); this.Cars = new List<string>(cars); } //单值属性 public string FirstName { get; set; } public string LastName { get; set; } public string Country { get; set; } public int Wins { get; set; } public int Starts { get; set; } //多值属性,车手可能多次获得冠军,所在的车队也可能不同 public IEnumerable<string> Cars { get; private set; } public IEnumerable<int> Years { get; private set; } public override string ToString() { return String.Format("{0} {1}", FirstName, LastName); } public int CompareTo(Racer other) { if (other == null) return -1; return string.Compare(this.LastName, other.LastName); } public string ToString(string format) { return ToString(format, null); } public string ToString(string format, IFormatProvider formatProvider) { switch (format) { case null: case "N": return ToString(); case "F": return FirstName; case "L": return LastName; case "C": return Country; case "S": return Starts.ToString(); case "W": return Wins.ToString(); case "A": return String.Format("{0} {1}, {2}; starts: {3}, wins: {4}", FirstName, LastName, Country, Starts, Wins); default: throw new FormatException(String.Format("Format {0} not supported", format)); } } }
//获得冠军的车队 [Serializable] public class Team { public Team(string name, params int[] years) { this.Name = name; this.Years = new List<int>(years); } public string Name { get; private set; } public IEnumerable<int> Years { get; private set; } } //获奖选手和年份 public class Championship { public int Year { get; set; } public string First { get; set; } public string Second { get; set; } public string Third { get; set; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具