2009-01-07 12 views
13

No estoy del todo seguro de cómo formular la pregunta, porque es un "¿por qué no funciona?" tipo de consulta.Limitaciones genéricas e implementación/herencia de la interfaz

he reducido mi tema en particular a este código:

public interface IFoo 
{ 
} 

public class Foo : IFoo 
{ 
} 

public class Bar<T> where T : IFoo 
{ 
    public Bar(T t) 
    { 
    } 

    public Bar() 
     : this(new Foo()) // cannot convert from 'Foo' to 'T' 
    { 
    } 
} 

Ahora, el tipo genérico T en la clase Bar<T> debe aplicar IFoo. Entonces, ¿por qué el compilador me da el error en el comentario? Sin duda, una instancia de Foo es un IFoo, y por lo tanto, se puede pasar como un representante del tipo genérico T?

¿Esto es una limitación del compilador o me falta algo?

Respuesta

13

También podría tener un Fiz que implementa IFoo que no está relacionado con Foo de cualquier otra manera:

public interface IFoo 
{ 
} 

public class Foo : IFoo 
{ 
} 

public class Fiz : IFoo 
{ 
} 

Foo foo = new Foo(); 
Fiz fiz = foo; // Not gonna compile. 

Lo que queremos es probablemente más como:

public class Bar<T> where T : IFoo, new() 
{ 
    public Bar(T t) 
    { 
    } 

    public Bar() 
     : this(new T()) 
    { 
    } 
} 

para que pueda tener

Bar<Foo> barFoo = new Bar<Foo>(); 
Bar<Fiz> barFiz = new Bar<Fiz>(); 
+0

Esto es dulce ya que no sabía que podrías hacer lo nuevo de T(), acabas de salvarme la vida en un proyecto en el que estoy trabajando. Saludos :) –

2

Si crea una clase Baz y luego el tipo genérico Bar baz = new Bar(), new Foo() como lo define su sobrecarga de constructor, no sería de tipo T, en este caso Baz.

+0

+1 Gracias yshuditelu. Le doy la respuesta aceptada a Andrew, ya que la suya es un poco más completa con las muestras de código (y usted solo tenía 8 segundos de diferencia). :) –

+0

De acuerdo (y gracias). –

0

es porque si crea una clase:

public class Fred : IFoo 
{ 
} 

Y luego instanciar Bar<T> así:

var bar = new Bar<Fred>(); 

Luego se viola las limitaciones de la clase como un Foo no es un Fred que es el actual T.

Puede forzarlo para compilar poniendo la secuencia molde (T)(IFoo)new Foo() en el constructor, pero vas a tener una InvalidCastException en tiempo de ejecución si el tipo real de T no es asignable a partir Foo.

Cuestiones relacionadas