[英]The return type of the members on an Interface Implementation must match exactly the interface definition?
根據CSharp語言規范。
接口定義了可以通過類和結構實現的契約。 接口不提供它定義的成員的實現 - 它僅指定必須由實現接口的類或結構提供的成員。
所以我有這個:
interface ITest
{
IEnumerable<int> Integers { get; set; }
}
我的意思是。 “我與一個屬性的合同是一個你可以枚舉的整數集合”。
然后我想要以下接口實現:
class Test : ITest
{
public List<int> Integers { get; set; }
}
我得到以下編譯器錯誤:
'Test'沒有實現接口成員'ITest.Integers'。 'Test.Integers'無法實現'ITest.Integers',因為它沒有匹配的返回類型'System.Collections.Generic.IEnumerable'。
只要我可以說我的Test類實現了ITest契約,因為int屬性的List實際上是int的IEnumerable。
那么c#編譯器告訴我錯誤的方式呢?
僅供參考,您想要的功能稱為“虛方法返回類型協方差”,正如您所發現的那樣,C#不支持它。 它是其他面向對象語言的一個特性,比如C ++。
雖然我們經常收到此功能的請求,但我們沒有計划將其添加到該語言中。 這不是一個可怕的特征; 如果我們擁有它,我會使用它。 但是我們有很多理由不這樣做,包括CLR不支持它,它為可版本化的組件添加了新的和有趣的故障模式,Anders認為它不是一個非常有趣的功能,而且我們有很多很多更高的優先級和有限的預算。
順便說一下,盡管人們一直要求我們使用虛方法返回類型協方差,但是沒有人要求虛方法形式參數類型相反 ,即使邏輯上它們本質上是相同的特征。 也就是說,我有一個帶有長頸鹿的虛擬方法/接口方法M,我想用一個帶動物的方法M來覆蓋/實現它。
你不能這樣做是因為你手上有一個重大問題,具體取決於實施情況,如果這是允許的話。 考慮:
interface ITest
{
IEnumerable<int> Integers { get; set; }
}
class Test : ITest
{
// if this were allowed....
public List<int> Integers { get; set; }
}
這將允許:
ITest test = new Test();
test.Integers = new HashSet<int>();
這會使Test的合同無效,因為Test說它包含List<int>
。
現在,您可以使用顯式接口實現來允許它滿足這兩個簽名,具體取決於它是從ITest
引用還是Test
引用調用:
class Test : ITest
{
// satisfies interface explicitly when called from ITest reference
IEnumerable<int> ITest.Integers
{
get
{
return this.Integers;
}
set
{
this.Integers = new List<int>(value);
}
}
// allows you to go directly to List<int> when used from reference of type Test
public List<int> Integers { get; set; }
}
簡單的事實是,如果界面說:
IInterface{
Animal A { get; }
}
然后該屬性的實現必須與該類型完全匹配 。 試圖將其實現為
MyClass : IInterface{
Duck A { get; }
}
不起作用 - 即使Duck
是Animal
相反,你可以這樣做:
MyClass : IInterface{
Duck A { get; }
Animal IInterface.A { get { return A; } }
}
即提供IInterface.A
成員的顯式實現,利用Duck
和Animal
之間的類型關系。
在你的情況下,這意味着至少實現吸氣劑,ITest.Integers為
IEnumerable<int> ITest.Integers { get { return Integers; } }
要實現setter,您需要樂觀地投射或在輸入值上使用.ToList()。
請注意,在這些顯式實現中使用A
和Integers
不是遞歸的,因為顯式接口實現在類型的公共視圖中是隱藏的 - 它們僅在調用者通過它的IInterface
/ ITest
接口實現與該類型進行通信時IInterface
。
您需要規范中的13.4.4:
出於接口映射的目的,類成員
A
匹配接口成員B
:•
A
和B
的性質,A和B的名稱和類型是相同的 ,和A具有相同的訪問B
(A
允許有額外的訪問器,如果它不是顯式接口成員實現)。
另外,您認為List<int> Integers { get; set; }
List<int> Integers { get; set; }
List<int> Integers { get; set; }
滿足合同IEnumerable<int> Integers { get; set; }
IEnumerable<int> Integers { get; set; }
IEnumerable<int> Integers { get; set; }
是假的。 即使規范以某種方式放寬而不要求返回類型相同,請注意具有公共setter的List<int>
類型的屬性與具有公共setter的IEnumerable<int>
類型的屬性不同。因為對於后者你可以分配一個int[]
的實例,但對於前者你不能。
你可以這樣做:
interface ITest
{
IEnumerable<int> Integers { get; set; }
}
class Test : ITest
{
public IEnumerable<int> Integers { get; set; }
public Test()
{
Integers = new List<int>();
}
}
因為Test不是ITest。 為什么? 使用ITest,您可以將數組設置為屬性Integers。 但你不能用一個測試。 使用.net 4.0,你可以做那樣的事情(協方差和反方差)但不完全是這樣,它在每種語言中都是不正確的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.