2012-04-11 49 views
0

我有以下LINQ Select哪個不起作用。我的linq選擇不起作用,我的foreach是

Data.Select(d => d.Value.IsDirty = true); //-- Not working 

我的更長的解決方法呢。

foreach (var d in Data) 
    d.Value.IsDirty = true; 

爲什麼我的第一個代碼不起作用?

+4

*在牆上*爆炸頭! – 2012-04-11 00:15:16

+1

不要產生使用LINQ的副作用。顧名思義,它只是查詢而不是改變狀態。 – Sandeep 2012-04-11 01:35:40

+2

Sandeep是正確的;你正在做的東西,LINQ是*專門設計,不做*。使用查詢*詢問有關數據的問題*。使用循環*更改數據*。永遠不會*使用查詢來更改數據結構。 – 2012-04-11 04:26:18

回答

4

Select()返回IEnumerable<…>,它具有能力遍歷輸入和調用特定的代碼,但實際上並沒有這樣做,直到你以某種方式枚舉它:

Data.Select(d => d.Value.IsDirty = true).ToList(); 

foreach (var _ in Data.Select(d => d.Value.IsDirty = true)) 
    ; // Do nothing 

但是,考慮到他們執行副作用(顯然是這裏的意圖),上述兩者都是惡業。不要使用它們。您的原始foreach是唯一明智的選擇。

+2

這兩個都是令人厭惡的。正確的答案是「你做錯了,試圖使用查詢來改變狀態,而是使用'foreach'循環。」 – jason 2012-04-11 12:59:35

+0

@Jason:我修改了我的問題,使我的立場更加清晰。但是,「噁心」?我們正在討論編程技巧,而不是戀物癖。 – 2012-04-12 12:50:31

8

投影函數,如SelectWhere等定義查詢。只需調用Select實際上並不實際任何事情,直到查詢被評估(幾乎可以肯定,在某個時候,由foreach)。

如果您要強制執行查詢(例如調用Count),您會發現它會生效。

然而,這是一種濫用。這些功能並非專門用於狀態更改操作。

-3

調用Select不會導致所需的副作用,即使您通過迭代元素來強制執行。 如果你想要副作用,你必須做foreach

例如:LINQ查詢=:

class MyValue 
{ 
    public MyValue(bool flag) { Flag = flag; } 

    public bool Flag { get; set; } 
} 

class MyValueContainer 
{ 
    public MyValueContainer(MyValue val) { MyVal = val; } 

    public MyValue MyVal { get; set; } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var someList = new List<MyValueContainer>(); 
     someList.Add(new MyValueContainer(new MyValue(true))); 
     someList.Add(new MyValueContainer(new MyValue(true))); 
     someList.Add(new MyValueContainer(new MyValue(false))); 
     someList.Add(new MyValueContainer(new MyValue(true))); 

     var trueCount = someList.Count(x => x.MyVal.Flag); // 3 
     var falseCount = someList.Count(x => !x.MyVal.Flag); // 1 

     // try causing side effect by calling Select 
     someList.Select(x => x.MyVal.Flag = false); 

     // force execution. call Count 
     trueCount = someList.Count(x => x.MyVal.Flag); // still 3... no side effect. 
     falseCount = someList.Count(x => !x.MyVal.Flag); // still 1... no side effect. 

     foreach (var x in someList) 
      x.MyVal.Flag = false; 

     trueCount = someList.Count(x => x.MyVal.Flag); // 0... side effect seen. 
     falseCount = someList.Count(x => !x.MyVal.Flag); // 4... side effect seen. 
    } 
} 
+2

-1。您不會強制執行查詢(事實上,您甚至不在任何地方存儲查詢)。這是不正確的; 'Select' *可能會導致副作用,如果你這樣使用,它只是臭的代碼。如果你把'someList.Select(x => x.MyVal.Flag = false).Count();',你會在後續的測試中看到副作用。 – 2012-04-11 01:09:45

+0

你是對的..對不起,我的壞。 – pnvn 2012-04-11 18:12:17