与generics参数的接口与使用generics方法的接口

假设我有这样的界面和具体实现

public interface IMyInterface { T My(); } public class MyConcrete : IMyInterface { public string My() { return string.Empty; } } 

所以我为strings创建MyConcrete实现,我可以为int提供一个更具体的实现。 那没关系。 但是,让我们说,我想做同样的事情,但使用通用方法,所以我有

 public interface IMyInterface2 { T My(); } public class MyConcrete2 : IMyInterface2 { public string My() { throw new NotImplementedException(); } } 

所以我有相同的IMyInterface2 ,但它通过T My()定义了通用行为。 在我的具体类中,我想实现My行为,但对于具体的数据类型 – string 。 但C#不允许我这样做。

我的问题是为什么我不能这样做? 换句话说,如果我可以创建MyInterface具体实现作为MyClass : MyInterface并在此时停止泛化,为什么我不能用generics方法T My()

您的通用方法实现也必须是通用的,因此它必须是:

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

为什么你不能在这里做My() ? 因为接口契约需要一个方法,可以使用任何类型参数T调用,并且您必须履行该合同。

为什么你不能在这一点上阻止一般性 因为它会导致以下情况:

类声明:

 public interface IMyInterface2 { T My(t value); } public class MyClass21 : IMyInterface2 { public string My(string value) { return value; } } public class MyClass22 : IMyInterface2 { public int My(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(); 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() method. Choose T to be int and call with value 2: item.My(2); // how would it work with item1, which has My implemented? } 

当您编写通用方法时,定义用于保留占位符。 调用方法时,实际类型会显示在图片中。 所以相反你应该写

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

当你调用方法时,你可以在那里使用字符串。

因为您的接口声明了一个通用方法T My() ,但您的实现没有实现具有该特定签名的函数。

为了达到你想要的效果,你需要在第一个例子中为界面提供T generic参数:

 public interface IMyInterface2 { T My(); } public class MyConcrete2 : IMyInterface2 { public string My() { throw new NotImplementedException(); } } 

您的解决方案不起作用有两个原因。

首先,界面是合同。 当您实现IMyInterface2您保证将实现名为My的函数,该函数接受generics类型参数并返回该类型。 MyConcrete2不会这样做。

其次,C#generics不允许任何类型的参数专门化。 (我希望C#支持这个。)这是C ++模板中常见的事情,你的例子可以编译,但如果他们没有用string调用MyMyConcrete2任何用法MyConcrete2将无法编译。