简体   繁体   中英

Compilation error with primitives types with implementations of generic methods of an interface

I want to write an interface which allows freedom in the implementation. Basically I don't know the return types neither param types of the methods. I just want derived classes to implement this contract with same method names and param numbers.

So I can do like this:

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();
    }
}

But I would much more prefer generic methods instead of the whole interface. But I don't understand why I can do this:

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();
    }
}

But with primitive types the compiler gives me errors:

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();
    }
}

I don't want to be able to chose what types to use when I instantiate an object of the class implementation. For example, I don't want to write an implementation like this:

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

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

And being able to do this:

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

And this doesn't work also:

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();
    }
}

Thank you

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

does not do what you think - FooExampleClass and FooExampleClass2 are not types, but type parameters which can be instantiated to any class. This means a client could do:

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

Your code only appears to work because it does nothing.

Generic methods like this have to work for any parameters the client chooses so there's no way to restrict the parameters to work for particular parameters. If you want to do that you need to move them to the interface definition which you have in your first example.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM