【问题标题】:Error assigning class implementing generic interface to generic variable [duplicate]将实现泛型接口的类分配给泛型变量时出错[重复]
【发布时间】:2017-03-03 06:33:21
【问题描述】:

参考InvalidCastException on Generics,我已经为我自己的应用程序调整了给定的答案。举个例子:

public interface IData
{
    string getValue();
}

public interface IController<in T> where T : IData
{
    string formString(T data);
}

public class DataImplA : IData
{
    public string getValue()
    {
        return "DataImplA";
    }
}

public class ControllerImplA : IController<DataImplA>
{
    public string formString(DataImplA data)
    {
        return "ControllerImplA, " + data.getvalue();
    }
}

public class Program
{
    private static IController<IData> controller;

    public static void main(string[] args)
    {
        // Line with error
        Program.controller = (IController<IData>)new ControllerImplA();

        Console.WriteLine(Program.controller.formString(new DataImplA()));
    }
}

在运行期间,指示的行将触发

InvalidCastException:无法将“ControllerImplA”类型的对象转换为“IController`1[IData] 类型。

我尝试更改为Program.controller = (IController&lt;IData&gt;)new ControllerImplA&lt;DataImplA&gt;();,但这会导致编译错误The non-generic type 'ControllerImplA' cannot be used with type arguments

然后我尝试将类定义更改为public class ControllerImplA&lt;DataImplA&gt; : IController&lt;DataImplA&gt;,但新的编译错误是:

类型“DataImplA”不能用作泛型类型或方法“IController T”中的类型参数“T”。没有从“DataImplA”到“IData”的装箱转换或类型参数转换。

我不想使用public class ControllerImplA&lt;T&gt; : IController&lt;T&gt;,因为约束是ControllerImplA只能使用DataImplAControllerImplB只能使用DataImplB等等。

我应该如何更正我的原始代码?

【问题讨论】:

  • 您在 IController 中链接的 T 是协变的(“out”),在您的示例中它是逆变的(“in”),这在这种情况下很重要,这就是为什么它在此示例中不起作用.但是,您不能只将 in 更改为 out,因为您使用类型 T 作为 formString 中的参数。所以简而言之 - 你不能做你想做的事,这是有充分理由的。
  • 想象一下你能够以某种方式转换为 IController 。现在您将 DataImplB 传递给 formString(其中 DataImplB 也实现了 IData)。但是您尝试投射的 ControllerImplA 只接受 DataImplA。应该发生什么?这就是不允许的原因。
  • 正确代码:IController&lt;DataImplA&gt; a = new ControllerImplA(); a = controller;
  • @SlavaUtesinov 您的代码有效,但在我的实际应用程序中,将在初始化期间读取配置文件,以确定要实例化的确切类并将其分配给单例controller。不同的客户端机器会有不同的配置。未来实现类的数量也应该可以扩展,因为每个类对应一种 COTS 技术。我怎样才能做到这一点?
  • 在反变的情况下是不可能的。

标签: c# generics casting


【解决方案1】:

在我看来,Generic 类实际上是类的占位符。通过类型“T”,它在运行时创建不同的类型/类。也就是说IController&lt;IData&gt;IController&lt;DataImplA&gt;是完全不同的类,没有继承关系。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-05
    • 1970-01-01
    • 2016-02-12
    • 2018-05-06
    相关资源
    最近更新 更多