[英]using EndsWith() inside List.Any() is not working as expected
[英]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.