首頁 > 軟體

c#中LINQ的基本用法(一)

2022-04-12 19:01:12

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>介面提供了各種擴充套件方法(擴充套件方法在https://www.jb51.net/article/243984.htm介紹到),以便使用者在實現了該介面的任意集合上使用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; }
          }

到此這篇關於c#中LINQ的基本用法的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com