与泛型参数的接口与使用泛型方法的接口

Jev*_*sov 36 .net c# clr

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

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

public class MyConcrete : IMyInterface<string>
{
    public string My()
    {
        return string.Empty;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

public class MyConcrete2 : IMyInterface2
{
    public string My<string>()
    {
        throw new NotImplementedException();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

Mar*_*zek 37

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

public class MyConcrete2 : IMyInterface2
{
    public T My<T>()
    {
        throw new NotImplementedException();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

类声明:

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; }
}
Run Code Online (Sandbox Code Playgroud)

用法:

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?
}
Run Code Online (Sandbox Code Playgroud)


Chr*_*eld 5

因为您的接口声明了一个泛型方法T My<T>(),但您的实现并未实现具有该特定签名的函数。

为了实现您想要的,您需要在第一个示例中向接口提供 T 泛型参数:

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

public class MyConcrete2 : IMyInterface2<string>
{
    public string My()
    {
        throw new NotImplementedException();
    }
}
Run Code Online (Sandbox Code Playgroud)