簡體   English   中英

如何為這個 C# 方法實現這個通用接口

[英]How to implement this generic interface for this C# method

我有以下界面:

public interface ICopyable
{
    void Copy<T>(T source) where T : class;
}

我試圖實現它,但我不斷收到此錯誤:

方法 'Foo.Core.Models.AggregateRoot.Copy(TListing)' 的類型參數 'TListing' 的約束必須匹配接口方法 'FooCore.Interfaces.ICopyable.Copy(T)' 的類型參數 'T' 的約束。 考慮改用顯式接口實現。

public abstract class AggregateRoot : ICopyable
{
    public virtual void Copy<TListing>(TListing newAggregateRoot) 
        where TListing : AggregateRoot
    {
       // my code here.
    }
}

在此處輸入圖片說明

為什么會失敗? 我的AggregateRoot是一個類。

假設您的代碼已編譯。 然后你可以這樣做:

class Derived : AggregateRoot
{
}

進而:

var derived = new Derived();
ICopyable copyable = derived;
copyable.Copy<string>("Hello!");

這很好,因為ICopyable.Copy<T>需要一個類的類型參數 - 而string是一個類。 但是它必須被分派到一個實際需要一個T : AggregateRoot的方法T : AggregateRoot 這將不得不在運行時失敗 - 因此編譯器只是事先拒絕它。

更籠統地說,問題在於您正在嘗試使用比接口所說的更嚴格的實現來實現特定的接口。 這不是類型安全的 - 它會違反關於輸入逆變的Liskov 替換原則

但是即使它類型安全的並且沒有違反 LSP,它仍然會被編譯器拒絕。 C# 要求專門化一個類並實現一個接口總是用精確的、不變的簽名和相同的約束來完成。 這在C# 規范中的13.4.3 泛型方法的實現中有詳細說明

當泛型方法隱式實現接口方法時,為每個方法類型參數給出的約束必須在兩個聲明中等效 [...]

但是,C# 仍然允許泛型接口(具有相同泛型類型定義)之間的隱式轉換存在差異。 因此,如果將代碼更改為以下內容,您的代碼將可以正常工作:

public interface ICopyable<in T>
    where T : class
{
    void Copy(T source);
}

public abstract class AggregateRoot : ICopyable<AggregateRoot>
{
    public virtual void Copy(AggregateRoot newAggregateRoot) 
    {
       // my code here.
    }
}

現在您可以執行以下操作,它可以編譯並且是類型安全的:

var derived = new Derived();
ICopyable<AggregateRoot> aggregateCopyable = derived;
ICopyable<Derived> derivedCopyable = aggregateCopyable;
derivedCopyable.Copy(derived);

暫無
暫無

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

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