簡體   English   中英

C#為什么Except和Where Enumerable給出了這個奇怪的結果?

[英]C# Why does Except and Where Enumerable Give This Weird Result?

我一直在調試這個生產錯誤,我迫切需要幫助,這對我來說也很有意思。

我簡化了代碼邏輯並為調試添加了一些打印輸出:

int[] a = { 2,2,2 };
var b = a.Where(x => x==2);

for(int i = 0; i < 3; i++)
{
    var c = b.Where(x => x==i);

    Console.WriteLine("iter {0} before - B Count: {1}, C Count: {2}", i, b.Count(), c.Count());

    if (c.Count() != b.Count())
        b = b.Except(c);

    Console.WriteLine("iter {0} after - B Count: {1}, C Count: {2}", i, b.Count(), c.Count());
}

Console.WriteLine("After Loop: B Count: {0}", b.Count());

有趣的是(奇怪),輸出是:

iter 0 before - B Count: 3, C Count: 0
iter 0 after - B Count: 1, C Count: 0
iter 1 before - B Count: 1, C Count: 0
iter 1 after - B Count: 1, C Count: 0
iter 2 before - B Count: 0, C Count: 0
iter 2 after - B Count: 0, C Count: 0
After Loop: B Count: 1

問題1:

為什么b.Count() == 0 at“iter 2 before”。 唯一的事情發生在“iter 1 after和iter 2 before”之間

var c = b.Where(x => x==i);

為什么這個代碼會改變b?

問題2:

為什么b.Count()在循環結束后變回1?

我非常感謝大家的幫助,指導我解決這個問題,謝謝!

由於linq的惰性求值,每次調用Count()時都會執行WhereExcept調用。 這里需要注意的重要一點是, i的值不會被記住,而是將所有先前Where調用的當前值取為i

為什么b.Count()== 0 at“iter 2 before”

此時, i已經增加到2 當您調用count時,將使用此值評估整個linq查詢,這意味着之前添加的“Except”調用已經刪除了所有內容!

為什么b.Count()在循環結束后變回1?

i等於3時,循環結束。現在當你評估整個linq查詢時, .Where(x => x==i)調用都不會返回任何內容,這反過來意味着沒有任何Except調用會刪除任何東西(除了重復之外)。

對於1 :“為什么這個代碼會改變b?”

它沒有。 添加(在循環開始時,在c之前):

Console.WriteLine("iter {0} before anything - B Count: {1}", i, b.Count());

b沒有變化。

2 :那是因為被捕獲的i 改成:

for(int tmp = 0 ; tmp < 3 ; tmp++) {
      int i = tmp;
    // ...
}

然后再試一次。 現在i的作用域確定在循環 ,並且相應地捕捉(在該迭代變量for循環的作用域確定的循環 ,對於復雜的原因;在一個foreach循環中,迭代變量是僅限內部或外循環依賴於你正在使用的C#版本)

像它的SQL對應的行為Except ,它消除了重復。 因此,它的行為就像在列表中調用Distinct

所以當你第一次執行Except

if (c.Count() != b.Count()) // c.Count() == 0, b.Count() == 3
    b = b.Except(c);

您只能獲得b的唯一元素,其中只有一個元素。

Enumerable.Except通過使用默認的相等比較器來比較值來產生兩個序列的集合差異。 集合不包含重復項。

這就是為什么序列在Except之后只包含一個2。

int[] onlyOneTwo = new[]{ 2,2,2 }.Except(Enumerable.Empty<int>()).ToArray();

所以Except 使用一個集合 Except ,空序列不會刪除任何內容。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM