2016-05-30 4 views
0

実装に自由を与えるインタフェースを作成したいと思います。基本的に私は戻り値の型もメソッドのparam型も知らない。私は、派生クラスに同じメソッド名とパラメータ番号でこの契約を実装したいだけです。インタフェースのジェネリックメソッドの実装によるプリミティブ型のコンパイルエラー

だから私はこのように行うことができます。

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(オブジェクトのparam)では "param"(オブジェクト型のため)を渡すことができなければなりませんが、あなたのbyte [] Learn(string param)は文字列を渡すことしかできません。インタフェースを満足しない。 – Evk

+0

ジェネリック医薬品の主なポイントは、あなたが迂回しようとしているものだと思います。最終的に型を指定する必要があります。メソッドやインタフェースではなく、 '' Learn''と '' 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

あなたの答えをありがとう。私は、私の場合、ジェネリックインターフェースを使わずにジェネリックメソッドだけを使うことは可能だと考えましたが、そうは思われません。メソッドの量が増えるにつれ、実装クラスはかなり醜く見え、読みにくくなります –

関連する問題