2013-07-11 86 views
25

比方說,我有這樣的接口和具體實施接口與泛型參數VS接口與通用方法

public interface IMyInterface<T> 
{ 
    T My(); 
} 

public class MyConcrete : IMyInterface<string> 
{ 
    public string My() 
    { 
     return string.Empty; 
    } 
} 

所以我對strings創建MyConcrete實現,我可以有一個int更具體的實施。沒關係。但是,讓我們說,我想做同樣的事情,但與一般的方法,所以我有

public interface IMyInterface2 
{ 
    T My<T>(); 
} 

public class MyConcrete2 : IMyInterface2 
{ 
    public string My<string>() 
    { 
     throw new NotImplementedException(); 
    } 
} 

所以我也有同樣IMyInterface2,但它定義了的T My<T>()手段仿製行爲。在我的具體類中,我想實現My行爲,但是對於具體的數據類型 - string。但是C#不允許我這樣做。

我的問題是爲什麼我不能這樣做? 換句話說,如果我可以創建MyInterface<T>的具體實現MyClass : MyInterface<string>並停止在這一點的通用性,爲什麼我不能用通用方法做到這一點 - T My<T>()

+1

當繼承類型時,你不能*減少*能力,你只能添加它們。 –

回答

29

你的泛型方法的實現必須是通用一樣,所以它必須是:

public class MyConcrete2 : IMyInterface2 
{ 
    public T My<T>() 
    { 
     throw new NotImplementedException(); 
    } 
} 

爲什麼你不能做My<string>()這裏?由於接口契約需要一種方法,因此可以使用任何類型參數T調用該方法,並且必須履行該合同。

爲什麼你不能在此停止通用因爲它會導致情況類似如下:

類聲明:

public interface IMyInterface2 
{ 
    T My<T>(t value); 
} 

public class MyClass21 : IMyInterface2 
{ 
    public string My<string>(string value) { return value; } 
} 

public class MyClass22 : IMyInterface2 
{ 
    public int My<int>(int value) { return value; } 
} 

用法:

var item1 = new MyClass21(); 
var item2 = new MyClass22(); 

// they both implement IMyInterface2, so we can put them into list 
var list = new List<IMyInterface2>(); 
list.Add(item1); 
list.Add(item2); 

// iterate the list and call My method 
foreach(IMyInterface2 item in list) 
{ 
    // item is IMyInterface2, so we have My<T>() method. Choose T to be int and call with value 2: 
    item.My<int>(2); 

    // how would it work with item1, which has My<string> implemented? 
} 
+1

它需要公衆'T我()' –

+0

如果我可以創造具體的執行MyInterface的作爲MyClass的:MyInterface的在這一點上,我爲什麼不能做到阻止這種通用與通用的方法 - T的我( )? –

+1

@JevgenijNekrasov檢查我的更新。當我的「我的」執行失敗時,我展示了一種情況。 – MarcinJuraszek

0

因爲你的接口聲明泛型方法T My<T>(),但你實現不實現具有該特定簽名的功能。

達到你想要什麼,你需要提供的T泛型參數的接口,那麼你的第一個例子:

public interface IMyInterface2<T> 
{ 
     T My(); 
} 

public class MyConcrete2 : IMyInterface2<string> 
{ 
    public string My() 
    { 
     throw new NotImplementedException(); 
    } 
} 
+0

我知道如何實現我想要的,我想知道爲什麼我不能阻止通用性,因爲我可以使用接口 –

2

當你寫泛型方法的定義是爲保持佔位符。調用該方法時,實際類型會顯示在圖片中。所以你應該寫

public T My<T>() 
{ 
    throw new NotImplementedException(); 
} 

當你調用這個方法時,你可以在那裏使用字符串。

+0

我想停止共享性,因爲我可以使用通用接口(例如, MyClass:MyInterface

0

您的解決方案不起作用有兩個原因。

首先,接口是合同。當你實現IMyInterface2時,你保證你將實現一個名爲My的函數,它接受一個泛型類型參數並返回該類型。 MyConcrete2不這樣做。

其次,C#泛型不允許任何類型的參數專門化。 (我希望C#支持這一點。)這是C++模板中常見的事情,您的示例可以編譯,但如果012xx的任何用法不能用string調用My,則將無法編譯。