我正在嘗試創建一個基本記錄型別,它將使用不同的實作Equals()值相等,因為它將使用 比較集合物件SequenceEqual(),而不是通過參考比較它們。
但是, Equals() 的實作并不像我期望的繼承那樣作業。
在下面的示例中,我有一個派生類,它有兩個不同的串列。在相等的默認實作下,這些記錄是不同的,因為它是通過參考相等而不是序列相等來比較串列。
如果我Equals()將基本記錄上的默認實作覆寫為始終 return true,則單元測驗將失敗,即使代碼正在呼叫RecordBase.Equals(RecordBase obj).
public abstract record RecordBase
{
public virtual bool Equals(RecordBase obj)
{
return true;
}
}
public record DerivedRecord : RecordBase
{
public DerivedRecord(ICollection<int> testCollection)
{
TestCollection = testCollection;
}
public ICollection<int> TestCollection { get; init; }
}
public class RecordTests
{
[Fact]
public void Equals_WhenCollectionHasSameValues_ReturnsTrue()
{
var recordTest1 = new DerivedRecord(new List<int>() { 1, 2, 3 });
var recordTest2 = new DerivedRecord(new List<int>() { 1, 2, 3 });
Assert.True(recordTest1.Equals(recordTest2));
}
}
有趣的是,如果我更改實作以便在Equals()上實作DerivedRecord,而不是在 上RecordBase,則單元測驗將通過。
public record DerivedRecord : RecordBase
{
public DerivedRecord(ICollection<int> testCollection)
{
TestCollection = testCollection;
}
public virtual bool Equals(DerivedRecord obj)
{
return true;
}
public ICollection<int> TestCollection { get; init; }
}
此外,此問題特定于記錄:如果我將第一個示例的實作更改為使用類,則兩個實體將評估為相等并且單元測驗將通過。
public abstract class RecordBase
{
public virtual bool Equals(RecordBase obj)
{
return true;
}
}
所以有一些東西試圖覆寫Equals()with 記錄的默認實作,其中派生記錄不會繼承基本記錄的實作。
Is there a reason for this? Intuitively, it seems like a derived record should be able to inherit a base record's implementation of value based equality. However, I've been reading through the C# 9.0 specification for records and I'm not sure if there is a synthesized implementation which is preventing this, or whether this is even possible using records.
uj5u.com熱心網友回復:
不幸的是,記錄不會按照您期望的方式運行。
當您宣告一條記錄時,您將免費獲得相等檢查運算子和方法。
您的基類只回傳true,但是當您將派生記錄宣告為 a 時record,您也會在其中獲得一個相等性檢查方法,如下所示:
public virtual bool Equals(DerivedRecord other)
{
return (object)this == other || (base.Equals(other) &&
EqualityComparer<ICollection<int>>.Default.Equals(
this.TestCollection,
other.TestCollection));
}
由于EqualityComparer<ICollection<int>>.Default.Equals做了一個簡單的參考比較,這兩個串列雖然內容相同,但并不認為是相等的,因此您回傳false.
如果您將型別更改class為與 相反record,Equals則不會添加編譯器生成的方法和相關運算子,您只剩下基類中的一個,即回傳true.
但是對于record型別,您將為每個繼承級別和型別獲得該方法。這也是為什么直接在派生記錄型別上實作它也會根據您的預期“作業”,因為這樣編譯器就不會為您生成一個。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/403389.html
標籤:
