接口實現差異的非破壞實現必須在返回類型中協變,並且在參數類型中是相反的。
例如:
public interface IFoo
{
object Flurp(Array array);
}
public class GoodFoo : IFoo
{
public int Flurp(Array array) { ... }
}
public class NiceFoo : IFoo
{
public object Flurp(IEnumerable enumerable) { ... }
}
兩者都是在 「新」 規則的法律,對不對?但這又如何:
public class QuestionableFoo : IFoo
{
public double Flurp(Array array) { ... }
public object Flurp(IEnumerable enumerable) { ... }
}
很難分辨哪種隱式實現在這裏更好。第一個是參數類型的精確匹配,但不是返回類型。第二個是完全匹配的返回類型,但不是參數類型。我傾向於第一個,因爲使用接口的人只能給它一個Array
,但它仍然不完全清楚。
到目前爲止這並不是最糟糕的。如果我們這樣做:
public class EvilFoo : IFoo
{
public object Flurp(ICollection collection) { ... }
public object Flurp(ICloneable cloneable) { ... }
}
哪一個獲獎?這是一個完全有效的過載,但是ICollection
和ICloneable
與彼此無關,並且Array
實現了它們兩者。我在這裏看不到一個明顯的解決方案。
它,只有當我們開始添加過載到接口本身變得更糟:
public interface ISuck
{
Stream Munge(ArrayList list);
Stream Munge(Hashtable ht);
string Munge(NameValueCollection nvc);
object Munge(IEnumerable enumerable);
}
public class HateHateHate : ISuck
{
public FileStream Munge(ICollection collection);
public NetworkStream Munge(IEnumerable enumerable);
public MemoryStream Munge(Hashtable ht);
public Stream Munge(ICloneable cloneable);
public object Munge(object o);
public Stream Munge(IDictionary dic);
}
好運試圖解開這個謎團沒有要瘋了。
當然,如果斷言接口實現應該只支持返回類型方差而不支持參數類型方差,那麼所有這些都是沒有意義的。但幾乎所有人都會認爲這樣的一個半實現被徹底打破並開始發送垃圾郵件報告,所以我不認爲C#團隊會這樣做。
我不知道這是爲什麼今天在C#中不支持它的官方原因,但它應該是它可能導致的那種「只寫」代碼的一個很好的例子,也是它的一部分C#團隊的設計理念是試圖阻止開發人員編寫糟糕的代碼。
如果'IClonable'接口在您的代碼之前被寫入,那麼Clone方法如何返回特定類型?我們唯一的保證是,無論您是否執行克隆,都會從「對象」派生出來。由於您必須遵守確切的接口定義,因此您必須返回界面所說的內容,即「對象」。 – 2010-03-23 17:49:56
在這裏,我想我Clone方法的實現應該能夠返回特定類型而不是IClonable的Clone()方法,當我實現IClonable接口時。但這是不允許的,我們得到一個編譯錯誤。所以我想知道原因,爲什麼協變或逆變的概念不允許實現一個接口。 – Amit 2010-03-24 04:13:33