6

考虑一下,我有以下 3 个类/接口:

class MyClass<T> { }

interface IMyInterface { }

class Derived : IMyInterface { }

我希望能够将 aMyClass<Derived>转换为 aMyClass<IMyInterface>或反之亦然:

MyClass<Derived> a = new MyClass<Derived>();
MyClass<IMyInterface> b = (MyClass<IMyInterface>)a;

但是如果我尝试,我会得到编译器错误:

Cannot convert type 'MyClass<Derived>' to 'MyClass<IMyInterface>'   

我确信我不能这样做有一个很好的理由,但我想不出一个。

至于我为什么要这样做 - 我想象的场景是您理想情况下希望使用的实例MyClass<Derived>以避免大量讨厌的强制转换,但是您需要将实例传递给接受MyClass<IMyInterface>.

所以我的问题是双重的:

  • 为什么我不能在这两种类型之间进行转换?
  • 有什么方法可以保持使用实例的好处,MyClass<Derived>同时仍然能够将其转换为MyClass<IMyInterface>
4

2 回答 2

5

这不起作用,因为 C# 仅支持接口和委托的类型参数的协变。如果你的类型参数只存在于输出位置(即你只从你的类中返回它的实例并且不接受它作为参数)你可以创建一个这样的接口:

interface IClass<out T> { }
class MyClass<T> : IClass<T> { }

这将允许你这样做:

IClass<Derived> a = new MyClass<Derived>();
IClass<IMyInterface> b = a;

老实说,这与您将要获得的结果差不多,这需要 C# 4 编译器才能工作。

于 2010-04-19T23:56:25.353 回答
3

通常不能这样做的原因是因为大多数类都不是简单的空示例。他们有方法:

class MyClass<T> 
{
    static T _storage;

    public void DoSomethingWith(T obj)
    {
        _storage = obj;
    }
}

interface IMyInterface { }

class Derived : IMyInterface { }

MyClass<Derived> a = new MyClass<Derived>();

现在,a有一个DoSomethingWith接受 aDerived并将其存储在 type 的静态变量中的方法Derived

MyClass<IMyInterface> b = (MyClass<IMyInterface>)a;

如果允许,b现在似乎有一个方法DoSomethingWith可以接受任何实现IMyInterface,然后在内部尝试将其存储在 type 的静态变量中Derived,因为它实际上仍然是 . 引用的同一个对象a

所以现在你有一个类型Derived存储的变量......谁知道呢。

于 2010-04-20T00:12:57.920 回答