2010-04-19 9 views
6

tener en cuenta, que tienen las siguientes 3 clases/interfaces:genéricos fundición y el tipo genérico

class MyClass<T> { } 

interface IMyInterface { } 

class Derived : IMyInterface { } 

Y yo quiero ser capaz de lanzar un MyClass<Derived> en una viceversa MyClass<IMyInterface> o:

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

Pero consigo errores de compilación si trato:

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

estoy seguro de que hay una muy buena re así que por qué no puedo hacer esto, pero no puedo pensar en ninguno.

En cuanto a por qué quiero hacer esto - El escenario que estoy imaginando es aquel en el que idealmente se quiere trabajar con una instancia de MyClass<Derived> para evitar muchos lanzamientos desagradables, sin embargo, debe pasar su instancia a un interfaz que acepta MyClass<IMyInterface>.

Así que mi pregunta es doble:

  • Por qué no puedo fundido entre estos dos tipos?
  • ¿Hay alguna forma de mantener la amabilidad de trabajar con una instancia de MyClass<Derived> mientras se puede convertir esto en MyClass<IMyInterface>?

Respuesta

5

Esto no funciona porque C# solo admite la covarianza en los parámetros de tipo de interfaces y delegados. Si existe el parámetro de tipo sólo en posiciones de salida (es decir, que sólo devuelven instancias de la misma clase y no lo acepta como argumento) podría crear una interfaz de esta manera:

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

Qué le permitiría a hacer esto:

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

Francamente esto es lo más cerca que vas a conseguir y esto requiere que el compilador de C# 4 a trabajar.

3

La razón por la que no puede hacer esto en general es porque la mayoría de las clases no son simples ejemplos vacíos. Tienen métodos:

class MyClass<T> 
{ 
    static T _storage; 

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

interface IMyInterface { } 

class Derived : IMyInterface { } 

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

Ahora, a tiene un método que acepta un DoSomethingWithDerived y lo almacena en una variable estática de tipo Derived.

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

Si eso se le permitió, b ahora parece tener un método DoSomethingWith que acepte nada que implementa IMyInterface, y entonces internamente intento de almacenarlo en una variable estática de tipo Derived, porque todavía es muy el mismo objeto al que se hace referencia en a.

Así que ahora tendría una variable del tipo Derived almacenando ... quién sabe qué.

Cuestiones relacionadas