简体   繁体   English

带通用参数的接口与带通用方法的接口

[英]Interface with generic parameter vs Interface with generic methods

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 . 因此,我为strings创建MyConcrete实现,可以为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>() . 因此,我具有相同的IMyInterface2 ,但它通过T My<T>()定义了通用行为。 In my concrete class I want to implement My behavior, but for concrete data type - string . 在我的具体课程中,我想实现My行为,但对于具体的数据类型为string But C# doesn't allow me to do that. 但是C#不允许我这样做。

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>() ? 换句话说,如果我可以将MyInterface<T>创建为MyClass : MyInterface<string>并在此时停止泛型,那么为什么不能使用泛型方法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? 为什么在这里不能执行My<string>() Because interface contract needs a method, that could be called with any type parameter T and you have to fulfill that contract. 因为接口协定需要一个方法,所以可以使用任何类型参数T调用该方法,而您必须履行该协定。

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?
}

Because your interface declares a generic method T My<T>() , but you implementation does not implement a function with that specific signature. 因为您的接口声明了泛型方法T My<T>() ,但是您的实现并未实现具有该特定签名的函数。

To achieve what you want, you need to provide the T generic parameter to the interface instead, in your first example: 为了实现所需的功能,需要在第一个示例中向接口提供T泛型参数:

public interface IMyInterface2<T>
{
        T My();
}

public class MyConcrete2 : IMyInterface2<string>
{
    public string My()
    {
        throw new NotImplementedException();
    }
}

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. 当您调用该方法时,可以在其中使用字符串。

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. 当实现IMyInterface2您保证将实现一个名为My的函数,该函数采用通用类型参数并返回该类型。 MyConcrete2 does not do this. MyConcrete2不执行此操作。

Second, C# generics do not allow any kind of type parameter specialization. 其次,C#泛型不允许任何类型的类型参数专门化。 (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 . (我希望C#支持这一点。)这在C ++模板中很常见,您的示例将在该模板中编译,但是如果MyConcrete2任何用法如果不使用string调用My都将无法编译。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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