【问题标题】:Why can't I use the same generic type with inherited interface?为什么我不能将相同的泛型类型与继承的接口一起使用?
【发布时间】:2010-07-01 14:22:21
【问题描述】:

嗨, 我有以下场景,我将尽我所能解释,如果这是一个愚蠢的问题,请提前道歉。 我有两个接口(出于本示例的目的,其中没有任何内容)

public interface interfaceA {}
public interface interfaceB: interfaceA {}

还有2个班

public classA<interfaceA> {}
public classB: classA<interfaceB> { }

现在在其他地方我也有一个接受泛型类型作为参数的方法:

public static void DoSomething( ClassA<interfaceB> p_val ) {}

好的,然后我在创建对象时使用这些类。

ClassB obj1 = new ClassB();
ClassA<interfaceA> obj2 = new ClassA<interfaceA>();

当我现在将 obj1 传递给 DoSomething() 时,一切都很好,但是当我尝试将 obj2 传递给我的 DoSomething() 方法时,我收到一个编译错误,说它无法从 interfaceA 转换为 interfaceB。

这是有道理的,因为在我的方法中,泛型参数类型显式地是 interfaceB。但是,如果我希望该方法同时接受泛型类型(obj1 和 obj2),我该怎么办?希望这是有道理的。

【问题讨论】:

  • 接口在哪里使用?您能否使用代码标记使您的代码更具可读性?

标签: c#


【解决方案1】:

怎么样

public static void DoSomething<T>( ClassA<T> p_val)
{}

无论类型参数是什么,它都接受 ClassA 的任何实例。或者,如果您只想在 T 是 InterfaceA 或其子类时接受 ClassA&lt;T&gt; 的实例,您可以这样做:

public static void DoSomething<T>( ClassA<T> p_val) where T : InterfaceA
{}

【讨论】:

    【解决方案2】:

    sepp2k 和Jordão 都可以解决您的问题。至于原因why(根据您的问题标题)...

    在 .NET 4.0 之前,covariance and contravariance 不允许在泛型中使用 - 您正在尝试使用逆变(从更广泛的基类到更窄的子类)。这就像将 classA&lt;object&gt; 指定给期望 classA&lt;string&gt; 的方法。

    无论ClassA 对interfaceB 做什么,你都不能保证obj2 能够完成它,因为obj2 不处理interfaceB 实例(也不隐式地处理它的消费者) .它仅适用于 interfaceA 实例。

    如果您使用的是 4.0,则可以通过接口和委托以有限的方式执行此操作。见Covariance and Contravariance in Generics。

    【讨论】:

    • 谢谢杰夫,我同意,一旦我在方法中使用它,我想这取决于我想用它做什么,在这种情况下,我认为协变和逆变可能会成为一个问题?
    • 完全正确 - 这绝对值得调查,因为这是否是一个问题取决于为什么 DoSomething 需要 ClassA&lt;interfaceB&gt;(而不是更一般的东西)以及消费者如何使用它。跨度>
    • 感谢大家的回复,绝对帮助我理解c#。
    【解决方案3】:

    这里有个误区:

    public class classA<interfaceA> {} 
    

    这不是interfaceA,它是一个与interfaceA 同名的类型参数。像这样尝试它,错误将是有意义的:

    public class classA<T> {} 
    

    也许这就是你真正想要的:

    public class classA<T> where T : interfaceA {} 
    

    但如果没有sepp2k 提出的更改,它仍然无法在您的示例中工作。

    【讨论】:

      【解决方案4】:

      最小的公共单元是接口 A,所以尝试在 DoSomthing 方法中声明接口 A 参数而不是 B。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多