2016-05-30 50 views
0

我想編寫一個接口,允許自由的實現。基本上我不知道返回類型的方法的參數類型。我只是希望派生類使用相同的方法名稱和參數號來實現此合約。編譯錯誤與基本類型與接口的通用方法的實現

所以,我可以這樣做:

public interface IImageRecognitionEngine<TFoo0, TFoo1, TFoo2, TFoo3> 
{ 
    TFoo0 Learn(TFoo1 param); 
    TFoo2 Recognize(TFoo3 param); 
} 

public class FooImageRecognitionEngine : IImageRecognitionEngine<byte[], string, List<double>, string> 
{ 
    public byte[] Learn(string param) 
    { 
     throw new NotImplementedException(); 
    } 

    public List<double> Recognize(string param) 
    { 
     throw new NotImplementedException(); 
    } 
} 

但我更喜歡通用的方法,而不是整個界面。但我不明白爲什麼我能做到這一點:

public interface IImageRecognitionEngine2 
{ 
    TFoo0 Learn<TFoo0, TFoo1>(TFoo1 param); 
    TFoo2 Recognize<TFoo2, TFoo3>(TFoo3 param); 
} 

public class FooExampleClass 
{ 

} 

public class FooExampleClass2 
{ 

} 

public class Foo1ImageRecognitionEngine2 : IImageRecognitionEngine2 
{ 
    public FooExampleClass Learn<FooExampleClass, FooExampleClass2>(FooExampleClass2 param) 
    { 
     throw new NotImplementedException(); 
    } 

    public FooExampleClass Recognize<FooExampleClass, FooExampleClass2>(FooExampleClass2 param) 
    { 
     throw new NotImplementedException(); 
    } 
} 

但隨着原始類型,編譯器給我的錯誤:

public class Foo2ImageRecognitionEngine2 : IImageRecognitionEngine2 
{ 
    public byte[] Learn<byte[], string>(string param) 
    { 
     throw new NotImplementedException(); 
    } 

    public List<double> Recognize<List<double>, string>(string param) 
    { 
     throw new NotImplementedException(); 
    } 
} 

我不希望能夠選擇使用什麼類型的當我實例化類實現的對象時。舉例來說,我不想寫這樣的實現:

public class Foo2ImageRecognitionEngine2 : IImageRecognitionEngine2 
{ 
    public TFoo0 Learn<TFoo0, TFoo1>(TFoo1 param) 
    { 
     throw new NotImplementedException(); 
    } 

    public TFoo2 Recognize<TFoo2, TFoo3>(TFoo3 param) 
    { 
     throw new NotImplementedException(); 
    } 
} 

,並能夠做到這一點:

var fooEngine = new Foo2ImageRecognitionEngine2(); 
fooEngine.Learn<string, int>(52); 

而且這不也是工作:

public interface IImageRecognitionEngine3 
{ 
    object Learn(object param); 
    object Recognize(object param); 
} 

public class Foo1ImageRecognitionEngine3 : IImageRecognitionEngine3 
{ 
    public byte[] Learn(string param) 
    { 
     throw new NotImplementedException(); 
    } 

    public List<double> Recognize(string param) 
    { 
     throw new NotImplementedException(); 
    } 
} 

謝謝

+0

但是你的任何實現都不能滿足這個接口。例如在對象Learn(object param)中,我必須能夠傳遞任何「param」(因爲它是object類型的),但是你的byte [] Learn(string param)只允許我傳遞一個字符串,所以它不滿足界面。 – Evk

+0

我認爲泛型的主要觀點是你試圖規避的。你*必須*最終指定一個類型。我想你想讓''''''''和'''Recognize'''對象通用,而不是方法或接口。然後那些可以採取任何你想要的類型,你可以保持界面清潔(和方法簽名)! – Ruskin

+0

你有代碼示例來分享嗎?我不確定要理解。我想要的是在我的程序中使用我的接口,並通過使用依賴注入在啓動時傳遞良好的實現。像這樣,我可以很容易地改變我使用的實現。 –

回答

2
public FooExampleClass Learn<FooExampleClass, FooExampleClass2>(FooExampleClass2 param) 
{ 
    throw new NotImplementedException(); 
} 

不會做你在想什麼 - FooExampleClassFooExampleClass2不是類型,而是可以實例化爲任何類的類型參數。這意味着客戶可以這樣做:

var e = new Foo1ImageRecognitionEngine2(); 
e.Learn<string, object>(new object()); 

您的代碼只顯示工作,因爲它什麼都不做。

像這樣的通用方法必須適用於客戶端選擇的任何參數,因此無法限制參數適用於特定參數。如果你想這樣做,你需要將它們移動到第一個例子中的接口定義。

+0

好的,謝謝你的回答。我認爲在我的情況下可能只使用通用方法而不使用通用接口,但似乎不是。隨着方法數量的增長,實現類看起來非常難看,難以閱讀 –