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

时间:2018-01-28 16:31:17

标签: c# generics inner-classes

我有一个带有两个嵌套类的基本类。其中一个嵌套类是实现一个接口,其中我有一个方法签名,其返回类型为嵌套对象。

这就是我得到的:

A类

using System;

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

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

A类接口

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

与泛型相同

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

B类接口

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();和类public Item<T> Get()时返回类型不同?有什么想法吗?

编辑:停止将错误代码格式化为blockquote,因为碎片会丢失。这不是我得到的正确信息。

2 个答案:

答案 0 :(得分:1)

当你有

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

您应该(取决于您的设置)获得compiler warning CS0693

  

类型参数“T”与外部类型“A”

中的类型参数同名

这是因为泛型类中的嵌套类将获取外部类的类型参数,例如

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

完全有效 - B获取与其外部类A相同的类型参数,因此可以使用它,就像它被定义为非嵌套类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

如果TA<T>中的B<T>是相同的类型参数(类型不能同时为structclass),但反而非常混乱。

如果在Visual Studio中查看,IntelliSense将显示以下内容:

Nested generic classes with IntelliSense

因此T范围内的A<T> T范围内的B<T>相同 - 后者< em>隐藏前者。

事实上,没有什么可以阻止你拥有

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

即使TA<T>的类型参数的名称B<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看到这个答案的小提琴。

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

答案 1 :(得分:0)

因为#include <iostream> using namespace std; int main () { cout <<"Fibonacci series " << endl; int* arr; int n = 0; cout << "Enter no to print \n"; cin >> n; arr = new int [n]; arr[0] = arr [1] = 1; for (int i = 2; i < 10; i++){ arr[i] = arr[i-1]+arr[i-2]; } for (int i = 0; i < 10; i++) cout << arr[i] << endl; delete[] arr; return 0; } A.Item是不同的类型,而您的接口合同是从A.Item<T>方法而不是Get返回项目。

如果你定义泛型类,你也需要通用接口,非泛型接口方法契约不能使用方法返回泛型类型,所以你可能也需要添加泛型接口对于泛型类型:

Item<T>

UPDATE:

您的界面合约指定public interface IInterface<T> { A<T>.Item<T> Get<T>(); } 以返回Get

A<T>.Item<T>

虽然您的实现类型A<T>.Item<T> Get(); 仅指定返回类型为B<T>

Item<T>

由于哪个编译器不允许

由于接口将返回类型指定为public Item<T> Get() { throw new NotImplementedException(); } ,因此它也应该是类A<T>.Item<T>Get方法的返回类型,否则它也会抱怨B<T> A<T>.Item<T> 1}}和Item<T>不同,因此更改B<T>之类的内容会修复错误:

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

您可以看到以下演示小提琴:

https://dotnetfiddle.net/f9Djbz