c#中LINQ的基本用法(一)
LINQ(Language Integrated Query,語(yǔ)言集成查詢),在C#語(yǔ)言中集成了查詢語(yǔ)法,可以用相同的語(yǔ)法訪問(wèn)不同的數(shù)據(jù)源。
LINQ提供了不同數(shù)據(jù)源的抽象層,所以可以使用相同的語(yǔ)法。
這里主要介紹LINQ的核心原理和C#中支持C# LINQ查詢的語(yǔ)言擴(kuò)展。
1.語(yǔ)法
使用LINQ查詢出來(lái)自巴西的所以世界冠軍。這里可以使用List<T>類的FindAll()方法,但使用LINQ查詢語(yǔ)法更簡(jiǎn)單
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查詢。該查詢不是通過(guò)這個(gè)賦值語(yǔ)句執(zhí)行的,而是使用foreach循環(huán)訪問(wèn)查詢時(shí)執(zhí)行的。
2.擴(kuò)展方法
編譯器會(huì)轉(zhuǎn)換LINQ查詢,以調(diào)用方法而不是LINQ查詢。LINQ為IEnumerable<T>接口提供了各種擴(kuò)展方法(擴(kuò)展方法在http://chabaoo.cn/article/243984.htm介紹到),以便用戶在實(shí)現(xiàn)了該接口的任意集合上使用LINQ查詢。
定義LINQ擴(kuò)展方法的一個(gè)類是System.Linq名稱空間中的Enumerable。只需要導(dǎo)入這個(gè)名稱空間,就打開(kāi)了這個(gè)類的擴(kuò)展方法的作用域。下面是Where()擴(kuò)展方法的實(shí)現(xiàn)代碼:
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; } } }
因?yàn)閃here()作為一個(gè)泛型方法,所以它可以用于包含在集合中的任意類型。實(shí)現(xiàn)了IEnumerable<T>接口的任意集合都支持它。
3.推遲查詢的執(zhí)行
前面提到,在運(yùn)行期間定義LINQ查詢表達(dá)式時(shí),查詢不會(huì)運(yùn)行。查詢?cè)诘鷶?shù)據(jù)項(xiàng)時(shí)才會(huì)運(yùn)行。
舉個(gè)例子:
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); } }
輸出:
因?yàn)椴樵冊(cè)诘鷷r(shí)才執(zhí)行,所以在第一次輸出后有添加項(xiàng)再輸出,會(huì)顯示又添加的項(xiàng)。
但在調(diào)用方法ToArray(),ToList等方法時(shí),不會(huì)延遲執(zhí)行:
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); } }
輸出:
下面是用到的類,后續(xù)的也需要用到這些代碼。
//這個(gè)類創(chuàng)建需要的列表 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; //返回一組冠軍車隊(duì) 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; } //多值屬性,車手可能多次獲得冠軍,所在的車隊(duì)也可能不同 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)); } } }
//獲得冠軍的車隊(duì) [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; } } //獲獎(jiǎng)選手和年份 public class Championship { public int Year { get; set; } public string First { get; set; } public string Second { get; set; } public string Third { get; set; } }
到此這篇關(guān)于c#中LINQ的基本用法的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
WPF仿三星手機(jī)充電界面實(shí)現(xiàn)代碼
這篇文章主要為大家詳細(xì)介紹了WPF仿三星手機(jī)充電界面實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-08-08C#基礎(chǔ)語(yǔ)法:Base關(guān)鍵字學(xué)習(xí)筆記
這篇文章主要介紹了C#基礎(chǔ)語(yǔ)法:Base關(guān)鍵字學(xué)習(xí)筆記,本文講解了它的一些基礎(chǔ)知識(shí)以及測(cè)試代碼,需要的朋友可以參考下2015-06-06C#簡(jiǎn)單實(shí)現(xiàn)IOC容器的示例代碼
IoC 的原理是通過(guò)將對(duì)象的創(chuàng)建和依賴關(guān)系的管理交給外部容器來(lái)實(shí)現(xiàn),從而降低了代碼的耦合度,提高了代碼的可維護(hù)性和可測(cè)試性,下面我們就來(lái)看看如何通過(guò)C#實(shí)現(xiàn)一個(gè)IOC容器吧2024-02-02