由于签名不同(使用泛型),C# 无法实现接口方法

C# cant implement interface method because of different signatures (using generics)

我有一个基本的 class 和两个嵌套的 class。其中一个嵌套的 class 正在实现一个接口,其中我有一个带有 return 类型的嵌套对象的方法签名。

这是我得到的:

Class一个

using System;

namespace Nested
{
    class A
    {
        public class Item
        {
            //Implementation 
        }

        class B : IInterface
        {
            //
            public Item Get()
            {
                throw new NotImplementedException();
            }
        }
    }
}

ClassA

的接口
namespace Nested
{
    internal interface IInterface
    {
        A.Item Get();
    }
}

与泛型相同

Class B

using System;


namespace Nested
{
    class A<T>
    {
        public class Item<T>
        {
            //Implementation 
        }

        class B<T> : IInterface<T>
        {
            //
            public Item<T> Get()
            {
                throw new NotImplementedException();
            }
        }
    }
}

classB

的接口
namespace Nested
{
    internal interface IInterface<T>
    {
        A<T>.Item<T> Get();
    }
}

第一个代码没有使用泛型,但运行良好。与此相比,泛型示例给出了以下错误:

Class1.cs(13,22): error CS0738: 'A<T>.B<T>' does not implement interface member 'IInterface<T>.Get()'. 'A<T>.B<T>.Get()' cannot implement 'IInterface<T>.Get()' because it does not have the matching return type of 'A<T>.Item<T>

为什么在接口使用A<T>.Item<T> Get();和classpublic Item<T> Get()时说return类型不同?有什么想法吗?

编辑:停止将错误代码格式化为块引用,因为片段正在丢失。那不是我收到的正确消息。

因为 A.ItemA.Item<T> 是不同的类型,您的接口契约是 return 来自 Get 方法的项目而不是 Item<T>

万一你在定义泛型 classes 时,你也需要泛型接口,非泛型接口方法契约不适用于方法 return 泛型类型,所以可能您还需要为通用类型添加一个通用接口:

public interface  IInterface<T>
{
   A<T>.Item<T> Get<T>();
}

更新:

您的接口合约指定 Get 到 return A<T>.Item<T> :

A<T>.Item<T> Get();

而您的实现类型 B<T> 仅将 return 类型指定为 Item<T> :

public Item<T> Get()
{
    throw new NotImplementedException();
}

由于编译器不允许

由于接口指定return类型为A<T>.Item<T>所以应该是class中Get方法的return类型 B<T> 也是,否则它也会抱怨 A<T>.Item<T>Item<T> 当然是不同的,所以像下面这样更改 B<T> 修复了错误:

    class B<T> : IInterface<T>
    {
        //
        public A<T>.Item<T> Get<T>()
        {
            throw new NotImplementedException();
        }
    }

你可以看下面的演示fiddle:

https://dotnetfiddle.net/f9Djbz

当你有

class A<T>
{
    class B<T> { }
}

你应该(根据你的设置)得到 compiler warning CS0693:

Type parameter 'T' has the same name as the type parameter from outer type 'A'

这是因为泛型 class 中的嵌套 class 将采用外部 class 的类型参数,例如

class A<T>
{
   class B
   {
       public T Value { get; set; }
   {
}

完全有效 - B 获得与其外部 class A 相同的类型参数,因此可以像定义为非嵌套 class 一样使用它] B<T>.

您的代码等同于

class A<T>
{
    class B<U> { }
}

或者说,AB中的类型参数不一样,你没希望满足接口。

如果你忽略那个警告(不推荐)可以做一些像这样的可怕的事情:

#pragma warning disable 0693

public class A<T> where T : struct
{
    public class B<T> where T : class
    {
    }
}

#pragma warning restore 0693

如果 A<T>B<T> 中的 T 是同一类型参数(一个类型不能同时是 struct和一个 class),但反而非常混乱。

如果在 Visual Studio 中查看,IntelliSense 将显示:

所以 A<T> 范围内的 T 与 [=18= 范围内的 T 不同 ] - 后者 隐藏 前者。

事实上,没有什么能阻止你

var ab = new A<double>.B<Object>();

即使类型参数的 name 对于 A<T>B<T> 都是 T。因此编译器警告。


我想你想要的是这个:

class A<T>
{
    public class Item
    {
        //Implementation 
    }

    class B : IInterface<T>
    {
        public Item Get()
        {
            throw new NotImplementedException();
        }
    }
}

internal interface IInterface<T>
{
    A<T>.Item Get();
}

https://dotnetfiddle.net/nBFVLw 查看此答案的 fiddle。

如果您不熟悉嵌套泛型类型的使用,它们可能会违反直觉。