常用LINQ關鍵字用法匯總


背景

傳統上,針對數據的查詢都以簡單的字符串表示,而沒有編譯時類型檢查或 IntelliSense 支持。此外,還需要針對每種數據源學習一種不同的查詢語言:SQL 數據庫、XML 文檔、各種 Web 服務等等。 LINQ 使查詢成為 C# 中的一流語言構造。 可以使用語言關鍵字和熟悉的運算符針對強類型化對象集合編寫查詢。

注意事項

版本需求:.NET Framework 3.5 或更高版本

查詢對象:SQL Server 數據庫、XML 文檔、ADO.NET 數據集以及支持 IEnumerable 或泛型 IEnumerable<T> 接口的任何對象集合

引用包:System.Linq

以下按照使用度排序介紹。

Where

用於過濾數據,減少IF分支語句。

例子:

            StringBuilder str = new StringBuilder();
            foreach (int item in list.Where(d => d % 2 == 0))
            {
                str.Append(item);
            }

老式IF用法:

            StringBuilder str = new StringBuilder();
            foreach (int item in list)
            {
                if (item % 2 == 0)
                {
                    str.Append(item);
                }
            }

Take

從數據源開始位置讀取指定的元素個數用。

例子:

            var list = Enumerable.Range(1, 100000);

            foreach (int item in list.Take(10))
            {
                Console.WriteLine(item.ToString());
            }

Select

抽取數據源中類型的指定元素組建成新的類型。主要用於簡化數據列或者轉換數據類型,以及獲取元素Index。

例子:

            var list = new List<Animal> {
                new Animal{ Name="hot dog",Sex=1,Age=10},
                new Animal{ Name="big dog",Sex=0,Age=11},
                new Animal{ Name="bin dog",Sex=0,Age=12},
                new Animal{ Name="baby dog",Sex=1,Age=13},
            };

            foreach (string item in list.Select(a => a.Name))
            {
                Console.WriteLine(item.ToString());
            }

            foreach (var item in list.Select(a => new { Name = a.Name, Length = a.Age * 2, Type = "S" }))
            {
                Console.WriteLine(item.ToString());
            }

            foreach (var item in list.Select((value, index) => new { Number = index, Name = value }))
            {
                Console.WriteLine(item.ToString());
            }

            foreach (string item in list.Select(a => a.Sex.ToString("D2")))
            {
                Console.WriteLine(item.ToString());
            }

            foreach (int item in list.Select(a => a.Age * 2))
            {
                Console.WriteLine(item.ToString());
            }

結果:

SelectMany

將數據源降維抽取,減少For循環。類似Select,適合多重子集的數據源抽取數據。

例子:

            var parameters = new Parameter[]
              {
                new Parameter() { Name = "正一", Numbers = new int[] { 1, 2, 3 } },
                new Parameter() { Name = "清次", Numbers = new int[] { 1, 3, 5 } },
                new Parameter() { Name = "誠三", Numbers = new int[] { 2, 4, 6 } },
                new Parameter() { Name = "征史", Numbers = new int[] { 9, 8, 7 } },
              };

            StringBuilder str = new StringBuilder();
            var result = parameters.SelectMany(value => value.Numbers);
            foreach (int value in result)
            {
                str.Append($"{value},");
            }
            Console.WriteLine(str.ToString());

結果:

如果使用Select就是如下寫法:

            var parameters = new Parameter[]
              {
                new Parameter() { Name = "正一", Numbers = new int[] { 1, 2, 3 } },
                new Parameter() { Name = "清次", Numbers = new int[] { 1, 3, 5 } },
                new Parameter() { Name = "誠三", Numbers = new int[] { 2, 4, 6 } },
                new Parameter() { Name = "征史", Numbers = new int[] { 9, 8, 7 } },
              };

            var results = parameters.Select(value => value.Numbers);

            StringBuilder str = new StringBuilder();
            foreach (int[] values in results)
            {
                foreach (int number in values)
                {
                    str.Append($"{number},");
                }
            }
            Console.WriteLine(str.ToString());

結果:

Distinct

去掉重復數據留下一個,一般用於基礎數據類型。如果是類需要指定比較方法。

            int[] dataA = new int[] { 0, 1, 3, 3, 2 };
            List<float> dataB = new List<float>() { 1.5f, 1.5f, 1.5f, 1.5f };

            IEnumerable<int> dataA_D = dataA.Distinct();
            IEnumerable<float> dataB_D = dataB.Distinct();

            foreach (var d in dataA_D)
            {
                Console.WriteLine(d);
            }
            foreach (var d in dataB_D)
            {
                Console.WriteLine(d);
            }

Any

用來判斷列表是否為空,速度比Count()快。如果是類,可以指定判斷條件。

            int[] numbersA = new int[] { };
            int[] numbersB = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

            var list = new List<Animal> {
                new Animal{ Name="hot dog",Sex=1},
                new Animal{ Name=null,Sex=0},
                new Animal{ Name="bin dog",Sex=0},
                new Animal{ Name="baby dog",Sex=1},
            };
            
            Console.WriteLine(numbersA.Any());
            Console.WriteLine(numbersB.Any());
            Console.WriteLine(list.Any(a => a.Name == null));

Join

兩組數據結合。也可以用來根據某個表排序數據。

public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>( this IEnumerable<TOuter> outer, IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector );

參數說明:

outer:結合的數據列表A

inner:結合的數據列表B

outerKeySelector:列表A的主鍵字段

innerKeySelector:列表B的主鍵字段

resultSelector:返回結果定義。(匿名類居多)

            PersonData[] persons = new PersonData[]
            {
            new PersonData() { Name = "正一郎", ItemID = 0 },
            new PersonData() { Name = "清次郎", ItemID = 1 },
            new PersonData() { Name = "誠三郎", ItemID = 2 },
            new PersonData() { Name = "征史郎", ItemID = 0 },
            };

            ItemData[] items = new ItemData[]
            {
            new ItemData() { ID = 0, Name = "" },
            new ItemData() { ID = 1, Name = "権力" },
            };

            var joinList = persons.Join(
                                    items,
                                    person => person.ItemID,
                                    item => item.ID,
                                    (person, item) => new { PersonName = person.Name, ItemName = item.Name });

            foreach (var item in joinList)
            {
                Console.WriteLine($"Person:{item.PersonName}, Item:{item.ItemName}");
            }

Except

求兩個數據列表的差分集合用。

            int[] numbersA = new int[] { 1, 2, 3, 4, 5 };
            int[] numbersB = new int[] { 8, 6, 4, 2, 0 };

            IEnumerable<int> results = numbersA.Except(numbersB);
            foreach (var d in results)
            {
                Console.WriteLine(d);
            }

自定義比較條件的情況

    class Parameter
    {
        public int ID { get; set; }
        public string Name { get; set; }

        public override string ToString()
        {
            return string.Format("ID:{0}, Name:{1}", ID, Name);
        }
    }
    class ParameterComparer : IEqualityComparer<Parameter>
    {
        public bool Equals(Parameter i_lhs, Parameter i_rhs)
        {
            if (i_lhs.ID == i_rhs.ID &&
                i_lhs.Name == i_rhs.Name)
            {
                return true;
            }
            return false;
        }

        public int GetHashCode(Parameter i_obj)
        {
            return i_obj.ID ^ i_obj.Name.GetHashCode();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Parameter[] dataA = new Parameter[]
            {
                new Parameter() { ID = 0, Name = "正一郎" },
                new Parameter() { ID = 5, Name = "清次郎" },
                new Parameter() { ID = 3, Name = "誠三郎" },
                new Parameter() { ID = 9, Name = "征史郎" },
            };
            Parameter[] dataB = new Parameter[]
            {
            new Parameter() { ID = 5, Name = "清次郎" },
            new Parameter() { ID = 3, Name = "誠三郎" },
            new Parameter() { ID = 2, Name = "征史郎" },
            };

            ParameterComparer compare = new ParameterComparer();
            IEnumerable<Parameter> results = dataA.Except(dataB, compare);

            foreach (var item in results)
            {
                Console.WriteLine(item.ToString());
            }
            Console.ReadKey();
        }
    }

Range

指定開始位置,指定個數的連續列表做成。

            IEnumerable<int> intSequenceA = Enumerable.Range(1, 5);
            IEnumerable<int> intSequenceB = Enumerable.Range(-1, 3);
            IEnumerable<int> intSequenceC = Enumerable.Range(100, 4);

            foreach (var d in intSequenceA)
            {
                Console.WriteLine(d);
            }
            Console.WriteLine("=========");
            foreach (var d in intSequenceB)
            {
                Console.WriteLine(d);
            }
            Console.WriteLine("=========");
            foreach (var d in intSequenceC)
            {
                Console.WriteLine(d);
            }

備注:https://www.urablog.xyz/entry/2018/07/10/070000


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM