我有以下LINQ Select
哪個不起作用。我的linq選擇不起作用,我的foreach是
Data.Select(d => d.Value.IsDirty = true); //-- Not working
我的更長的解決方法呢。
foreach (var d in Data)
d.Value.IsDirty = true;
爲什麼我的第一個代碼不起作用?
我有以下LINQ Select
哪個不起作用。我的linq選擇不起作用,我的foreach是
Data.Select(d => d.Value.IsDirty = true); //-- Not working
我的更長的解決方法呢。
foreach (var d in Data)
d.Value.IsDirty = true;
爲什麼我的第一個代碼不起作用?
Select()
返回IEnumerable<…>
,它具有能力遍歷輸入和調用特定的代碼,但實際上並沒有這樣做,直到你以某種方式枚舉它:
Data.Select(d => d.Value.IsDirty = true).ToList();
或
foreach (var _ in Data.Select(d => d.Value.IsDirty = true))
; // Do nothing
但是,考慮到他們執行副作用(顯然是這裏的意圖),上述兩者都是惡業。不要使用它們。您的原始foreach
是唯一明智的選擇。
這兩個都是令人厭惡的。正確的答案是「你做錯了,試圖使用查詢來改變狀態,而是使用'foreach'循環。」 – jason 2012-04-11 12:59:35
@Jason:我修改了我的問題,使我的立場更加清晰。但是,「噁心」?我們正在討論編程技巧,而不是戀物癖。 – 2012-04-12 12:50:31
投影函數,如Select
,Where
等定義查詢。只需調用Select
實際上並不實際做任何事情,直到查詢被評估(幾乎可以肯定,在某個時候,由foreach
)。
如果您要強制執行查詢(例如調用Count
),您會發現它會生效。
然而,這是一種濫用。這些功能並非專門用於狀態更改操作。
調用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.
}
}
-1。您不會強制執行查詢(事實上,您甚至不在任何地方存儲查詢)。這是不正確的; 'Select' *可能會導致副作用,如果你這樣使用,它只是臭的代碼。如果你把'someList.Select(x => x.MyVal.Flag = false).Count();',你會在後續的測試中看到副作用。 – 2012-04-11 01:09:45
你是對的..對不起,我的壞。 – pnvn 2012-04-11 18:12:17
*在牆上*爆炸頭! – 2012-04-11 00:15:16
不要產生使用LINQ的副作用。顧名思義,它只是查詢而不是改變狀態。 – Sandeep 2012-04-11 01:35:40
Sandeep是正確的;你正在做的東西,LINQ是*專門設計,不做*。使用查詢*詢問有關數據的問題*。使用循環*更改數據*。永遠不會*使用查詢來更改數據結構。 – 2012-04-11 04:26:18