C# 方法泛型与类实现接口

时间:2021-02-05 17:11:57

标签: c# .net generics interface

更新:这不像我希望的那样工作,正如其他人在下面所说的那样,这不是一个真正有效的方法。将以另一种方式处理我需要的东西。

我创建了一个接口,其中包含一个使用泛型参数的方法和一个实现它的类。但是在类实现中,我收到一个错误,即该类没有实现该类上的成员。这看起来很奇怪。

interface InterfaceA
{
    String MethodA<T>(T obj);
}

public class ClassA : InterfaceA
{
    public String name { get; set; }

    public ClassA()
    {
        this.name = "My Name";
    }

    public String MethodA<ClassA>(ClassA aClass)
    {
        String result = aClass.name;    //ERROR IS ON THIS LINE
        return result;
    }   
}

public class ClassB : InterfaceA
{
    public String test1 { get; set; }

    public ClassB()
    {
        this.test1 = String.Empty;
    }

    public String MethodA<ClassB>(ClassB obj)
    {
        String result = obj.test1;
        return result;
    }
}

public class ClassC : InterfaceA
{
    public String test2 { get; set; }

    public ClassC()
    {
        this.test2 = String.Empty;
    }

    public String MethodA<ClassC>(ClassC obj)
    {
        String result = obj.test2;
        return result;
    }
}

这给出了“错误 CS1061 'ClassA' 不包含 'name' 的定义,并且无法找到接受类型为 'ClassA' 的第一个参数的可访问扩展方法 'name'(您是否缺少 using 指令或程序集参考?)"

我确定这里有问题,但我不确定是什么。

3 个答案:

答案 0 :(得分:4)

该问题很可能是由于您将 ClassA 名称重新用于泛型类型所致。在这种情况下,这隐藏了 ClassA 的真正定义。因此,为它使用另一个名称,在 C# 中使用 T 是很常见的。现在它可以是任何类型,但如果您想确保它具有 name 属性,那么您需要一个泛型类型约束。例如,这将起作用:

interface InterfaceA
{
    string MethodA<T>(T obj) where T : ClassA;
                           //^^^^^^^^^^^^^^^^
}

public class ClassA : InterfaceA
{
    public String name { get; set; }

    public ClassA()
    {
        this.name = "My Name";
    }

    public string MethodA<T>(T aClass) where T : ClassA
                                     //^^^^^^^^^^^^^^^^

    {
        String result = aClass.name;
        return result;
    }
}

当然,现在 ClassAInterfaceA 之间存在一种奇怪的关系,因此您可能希望将 name 属性提取出来,因为它也是自己的接口。例如:

public interface INamed
{
    string name { get; }
}

现在您的其他代码将如下所示:

interface InterfaceA
{
    string MethodA<T>(T obj) where T : INamed;
                           //^^^^^^^^^^^^^^^^
}

public class ClassA : InterfaceA, INamed
{
    public String name { get; set; }

    public ClassA()
    {
        this.name = "My Name";
    }

    public string MethodA<T>(T aClass) where T : INamed
                                     //^^^^^^^^^^^^^^^^

    {
        String result = aClass.name;
        return result;
    }
}

答案 1 :(得分:2)

忽略您知道 ClassA 具有 name 属性这一事实。

编译器看到 MethodAInterfaceA(ClassA 实现的接口)的成员。该方法在 T 类型中是通用的,其中 T 没有约束。您正在使用 MethodA 作为类型参数实现 ClassA。您可以使用任何类型。当您调用 aClass.name getter 时,编译器会说“嘿,T 没有限制,您不能使用它的任何成员”。

要解决此问题,请添加如下界面:

public interface IHaveAName 
{
    string name {get;}
}

然后将您的接口定义更改为:

interface InterfaceA
{
    String MethodA<T>(T obj) where T: IHaveAName;
}

然后声明 ClassA 实现了两个接口:

public class ClassA : InterfaceA, IHaveAName

您可能想重新考虑您在做什么(我的猜测是,如果这不是一个带有无意义名称的虚拟示例,那么您这样做的原因会更明显)。鉴于您所提供的信息,很难理解为什么您要以这种方式组织事物。

答案 2 :(得分:0)

如果在给定的类中你总是想调用具有相同参数类型的方法, 解决方案是将泛型类型参数添加到接口中:

interface InterfaceA<T>
{
    String MethodA(T obj);
}

那么你就可以这样实现了

public class ClassA : InterfaceA<ClassA>
{
    public String name { get; set; }

    public ClassA()
    {
        this.name = "My Name";
    }

    public String MethodA(ClassA aClass)
    {
        String result = aClass.name;    //No more error here.
        return result;
    }   
}