Let's say I have such interface and concrete implementation
public interface IMyInterface<T>
{
T My();
}
public class MyConcrete : IMyInterface<string>
{
public string My()
{
return string.Empty;
}
}
So I create MyConcrete implementation for strings, I can have one more concrete implementation for int. And that's ok. But let's say, that I want to do the same thing, but with generic methods, so I have
public interface IMyInterface2
{
T My<T>();
}
public class MyConcrete2 : IMyInterface2
{
public string My<string>()
{
throw new NotImplementedException();
}
}
So I have the same IMyInterface2, but which defines generic behavior by means of T My<T>(). In my concrete class I want to implement My behavior, but for concrete data type - string. But C# doesn't allow me to do that.
My question is why I cannot do that?
In other words, if i can create concrete implementation of MyInterface<T> as MyClass : MyInterface<string> and stop genericness at this point, why I can't do that with generic method - T My<T>()?
Your generic method implementation has to be generic as well, so it has to be:
public class MyConcrete2 : IMyInterface2
{
public T My<T>()
{
throw new NotImplementedException();
}
}
Why you can't do My<string>() here? Because interface contract needs a method, that could be called with any type parameter T and you have to fulfill that contract.
Why you can't stop genericness in this point? Because it would cause situations like following:
Class declarations:
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; }
}
Usage:
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?
}
when you write the Generic Method the Definition is for keeping the placeholder. Actual Type comes into picture when you call the method. so instead you should write
public T My<T>()
{
throw new NotImplementedException();
}
and when you call the method you can use the string there.
Because your interface declares a generic method T My<T>(), but you implementation does not implement a function with that specific signature.
To achieve what you want, you need to provide the T generic parameter to the interface instead, in your first example:
public interface IMyInterface2<T>
{
T My();
}
public class MyConcrete2 : IMyInterface2<string>
{
public string My()
{
throw new NotImplementedException();
}
}
Your solution does not work for two reasons.
First, an interface is a contract. When you implement IMyInterface2 you guarantee that you will implement a function named My that takes a generic type parameter and returns that type. MyConcrete2 does not do this.
Second, C# generics do not allow any kind of type parameter specialization. (I do wish C# supported this.) This is a common thing in C++ templates where your example would compile, but any usages of MyConcrete2 would fail to compile if they don't call My with a string.
来源:https://stackoverflow.com/questions/17596186/interface-with-generic-parameter-vs-interface-with-generic-methods