Casting generics and the generic type

戏子无情 提交于 2020-01-03 10:54:48

问题


Consider, I have the following 3 classes / interfaces:

class MyClass<T> { }

interface IMyInterface { }

class Derived : IMyInterface { }

And I want to be able to cast a MyClass<Derived> into a MyClass<IMyInterface> or visa-versa:

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

But I get compiler errors if I try:

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

I'm sure there is a very good reason why I cant do this, but I can't think of one.

As for why I want to do this - The scenario I'm imagining is one whereby you ideally want to work with an instance of MyClass<Derived> in order to avoid lots of nasty casts, however you need to pass your instance to an interface that accepts MyClass<IMyInterface>.

So my question is twofold:

  • Why can I not cast between these two types?
  • Is there any way of keeping the niceness of working with an instance of MyClass<Derived> while still being able to cast this into a MyClass<IMyInterface>?

回答1:


This does not work because C# only supports covariance on the type parameters of interfaces and delegates. If your type parameter exists only in output positions (i.e. you only return instances of it from your class and don't accept it as an argument) you could create an interface like this:

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

Which would allow you to do this:

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

Honestly that is about as close as you are going to get and this requires the C# 4 compiler to work.




回答2:


The reason you cannot do this in general is because most classes are not simple empty examples. They have methods:

class MyClass<T> 
{
    static T _storage;

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

interface IMyInterface { }

class Derived : IMyInterface { }

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

Now, a has a method DoSomethingWith that accepts a Derived and stores it in a static variable of type Derived.

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

If that was allowed, b would now appear to have a method DoSomethingWith that accepts anything that implements IMyInterface, and would then internally attempt to store it in a static variable of type Derived, because it's still really the same object referred to by a.

So now you'd have a variable of type Derived storing... who knows what.



来源:https://stackoverflow.com/questions/2671676/casting-generics-and-the-generic-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!