C# 带泛型参数的接口 vs 带泛型方法的接口

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17596186/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 09:58:57  来源:igfitidea点击:

Interface with generic parameter vs Interface with generic methods

c#.netclr

提问by Jevgenij Nekrasov

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

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

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 Mybehavior, but for concrete data type - string. But C# doesn't allow me to do that.

所以我有相同的IMyInterface2,但它通过T My<T>(). 在我的具体类中,我想实现My行为,但对于具体的数据类型 - string. 但是 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>as 的具体实现MyClass : MyInterface<string>并停止泛型,为什么我不能用泛型方法来做到这一点 - T My<T>()

采纳答案by MarcinJuraszek

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 Tand you have to fulfill that contract.

为什么My<string>()这里做不到?因为接口契约需要一个方法,可以用任何类型参数调用它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?
}

回答by Christoffer Mansfield

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

回答by Rakesh

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.

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

回答by IngisKahn

Your solution does not work for two reasons.

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

First, an interface is a contract. When you implement IMyInterface2you guarantee that you will implement a function named Mythat takes a generic type parameter and returns that type. MyConcrete2does not do this.

首先,接口是一个契约。当您实现时,IMyInterface2您保证您将实现一个名为的函数My,该函数接受一个泛型类型参数并返回该类型。 MyConcrete2不这样做。

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 MyConcrete2would fail to compile if they don't call Mywith a string.

其次,C# 泛型不允许任何类型的类型参数特化。(我确实希望 C# 支持这一点。)这在 C++ 模板中很常见,您的示例将在其中进行编译,但是MyConcrete2如果它们不My使用string.