簡體   English   中英

當假定為false時,List.Any()返回true

[英]List.Any() returning true when false was expected

我們今天在代碼中遇到了一個錯誤。 我們有幾個列表,其中數據的關鍵是枚舉。 有多個不同的枚舉用作鍵(下面的代碼中的Foo.Bar1和Foo.Bar2)。

所有測試都有一個包含1個項目的DataField列表,其中鍵設置為其中一個枚舉值。 第一次和最后一次測試按預期運行。 第二次測試預計會成功,但失敗了。 閱讀代碼時似乎是合法的。

我的假設是,通過取消裝箱變量,將枚舉值轉換為整數值並進行比較。 這使它們相等,從而返回true,從而使Any()方法也返回true。 這個對嗎? 或者還有什么事嗎?

我們應該在第三次測試中用equals()方法編寫比較...

如果在下面的單元測試中重新創建了一個非常簡化的問題版本。

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System.Linq;

namespace EnumCastTest
{
    [TestClass]
    public class UnitTest1
    {
        public class DataField
        {
            public Enum Key { get; set; }
        }

        class Foo
        {
            public enum Bar1 { A }
            public enum Bar2 { B }
        }


        [TestMethod]
        public void Field_With_Bar1_A_Should_Return_True()
        {
            List<DataField> fields = new List<DataField> {
                new DataField() { Key = Foo.Bar1.A} };

            Assert.IsTrue(fields.Any(q => (Foo.Bar1)q.Key == Foo.Bar1.A));
        }

        [TestMethod]
        public void Field_Without_Bar1_A_Should_Return_False()
        {
            List<DataField> fields = new List<DataField> {
                new DataField() { Key = Foo.Bar2.B} };

            Assert.IsFalse(fields.Any(q => (Foo.Bar1)q.Key == Foo.Bar1.A));
        }

        [TestMethod]
        public void Field_Without_Bar1_A_Should_Return_False2()
        {
            List<DataField> fields = new List<DataField> {
                new DataField() { Key = Foo.Bar2.B} };

            Assert.IsFalse(fields.Any(q => Foo.Bar1.A.Equals(q.Key)));
        }
    }
}

發生這種情況是因為以下內容返回true

var x = Foo.Bar1.A;
var y = (Foo.Bar2)x;
Console.WriteLine(y == Foo.Bar2.B);

枚舉在內部由整數值表示,默認情況下使用的類型是int

每個枚舉類型都有一個基礎類型,除了char之外,它可以是任何整數類型。 枚舉元素的默認基礎類型是int。

將一個枚舉類型轉換為另一個枚舉類型時使用此基礎類型。 因此,對於枚舉值,正在使用整數值,然后在此基礎上創建新的枚舉值。

從本質上講,這個過程是這樣的:

var x = Foo.Bar1.A;
int integral = (int)x;
var y = (Foo.Bar2)integral;

除非您使用每個枚舉成員明確指定數字,否則默認情況下,枚舉聲明中的位置決定從0開始的整數值。

因此,在上面的例子中, integral將是0 ,因為Bar1.A是第一構件Bar1 Bar2的第一個成員是Bar2.B ,這就是你得到的結果。

因此測試失敗的原因是因為在將一個枚舉轉換為另一個類型時,類型標識將丟失。 通常,枚舉只在自己域中產生真正意義,即當您將一個成員與同一枚舉的另一個成員進行比較時。

我想,每個枚舉都轉換為它的基礎類型 - Int32。 由於您沒有為每個值設置值,因此它們假設為零。

你將Foo.Bar2枚舉設置為值B,並且你正在檢查值為A的Foo.Bar1枚舉。嘗試檢查正確的枚舉。 如下面的代碼:

new DataField() { Key = Foo.Bar1.B} };

        Assert.IsFalse(fields.Any(q => (Foo.Bar1)q.Key == Foo.Bar1.A));

我想你希望枚舉值和類型相同,Any(...)返回true。

    [TestMethod]
    public void Field_Without_Bar1_A_Should_Return_False()
    {
        List<DataField> fields = new List<DataField> {
            new DataField() { Key = Foo.Bar2.B} };

        Assert.IsFalse(fields.Any(q => (q.Key is Bar1) && (Foo.Bar1)q.Key == Foo.Bar1.A));
    }

如果第一個謂詞為真,則評估第二個謂詞。

暫無
暫無

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

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