[C#.NET] 如果可以 請盡量使用LINQ查詢語法而不是使用迴圈

  • 76813
  • 0
  • 2013-07-05

[C#.NET] 如果可以 請盡量使用LINQ查詢語法而不是使用迴圈

我相信在for/foreach迴圈絕對是大多數人還在使用的控制結構,假設我有以下的Member類別,_memberList 則是Member類別集合

 

public struct Member
{
    public string Name { get; set; }
    public int Age { get; set; }
    public List<string> Phones { get; set; }
}

List<Member> _memberList = new List<Member>();
private void Form1_Load(object sender, EventArgs e)
{
    this._memberList = new List<Member>() 
    { 
        new Member(){Name="Yao",Age=18,Phones=new List<string>(){"0911123456789","0912123456789"}},
        new Member(){Name="gy",Age=20,Phones=new List<string>(){"0913123456789","0914123456789"}},
        new Member(){Name="LaLa",Age=19,Phones=new List<string>(){"0915123456789","0916123456789"}},
        new Member(){Name="9GY",Age=12,Phones=new List<string>(){"0917123456789","0918123456789"}}
    };
}

在LINQ還沒有出現以前foreach這是我很常用的查詢方式,比如說我想要查詢集合內的某個屬性,使用foreach迴圈來處理,用來找尋是否有Age大於10的項目

foreach的寫法:

 

List<Member> query = new List<Member>();
foreach (Member item in this._memberList)
{
    if (item.Age > 10)
    {
        query.Add(item);
    }
}

在LINQ裡這麼做:

 

var find = from data in this._memberList
           where data.Age > 10
           select data;

foreach (var item in find)
{
     //TODO:
}

或是找尋是否有某個關鍵字存在

foreach的寫法:

foreach (var item in this._memberList)
{
    if (item.Name.ToUpper() == "YAO")
    {
        query.Add(item);
    }
}

在LINQ裡這麼做:

var find = from data in this._memberList
           where data.Name.ToUpper() == "YAO"
           select data;
foreach (var item in find)
{
      //TODO:
}

在LINQ裡我們的程式語法由"命令式"變成了"聲明式",我們只管下達命令不用管它的實作方式,在閱讀上LINQ優於傳統的for/foreach迴圈

from data in this._memberList    →指定資料來源
where data.Age > 10              →條件
select data;                     →查詢結果

 

除了閱讀性,還有修改上的彈性,由其是當需求一變動的時候,LINQ則能很快的變動,比如說PM騎著機車要變更需求,找出 "大於10歲" "名字很GY的人" "並且由小到大排序"

foreach的寫法:

List<Member> query = new List<Member>();
foreach (Member item in this._memberList)
{
    if (item.Age > 10 && item.Name.ToUpper().IndexOf("GY") >= 0)
    {
        query.Add(item);
    }
}
query.Sort(CompareMember);

int CompareMember(Member a, Member b)
{
    return a.Age – b.Age; 
} 

在LINQ裡這麼做:

 

var find = from data in this._memberList
           where data.Age > 10 && data.Name.ToUpper().IndexOf("GY") >= 0
           orderby data.Age
           select data;


有沒有發現差異性越來越明顯了,好的,若需求再變更時程式碼會有什麼變化呢!?這時開著卡車來的PM,要求找出特定的電話號碼 0917123456789

foreach的寫法

巢狀迴圈的寫法越讀起來越來越吃力了,好吧!!或許有人會說我把巢狀迴圈拆開不就好了,就算拆開也沒有辦法像LINQ那麼乾淨,對吧!?

List<Member> query = new List<Member>();
foreach (Member item in this._memberList)
{
    if (item.Age > 10 && item.Name.ToUpper().IndexOf("GY") >= 0)
    {
        foreach (string phone in item.Phones)
        {
            if (phone == "0917123456789")
            {
                query.Add(item);
            }
        }
    }
}
query.Sort(CompareMember);

LINQ裡這麼做:

 

var find = from data in this._memberList
           where data.Age > 10 
           where data.Name.ToUpper().IndexOf("GY") >= 0
           orderby data.Age
           from phone in data.Phones
           where phone == "0917123456789"
           select data;

 


後記:

雖然LINQ效能並沒有想像中的好,不過它的查詢功能的可讀性以及修改彈性都很高,在上面的例子我會捨棄效能來迎合這樣的閱讀性及修改彈性,所以如果可以我都會盡可能的使用LINQ。

 

 

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo