¿Alguien entiende por qué tener una restricción genérica donde la clase es diferente a la interfaz? Este código no compila:
public interface IInterface { } public class Class<T> where T : IInterface { public void Do() { IEnumerable<IInterface> ret = GetEnumerable(); } public IEnumerable<T> GetEnumerable() { return new T[0]; } }mientras que, al cambiar IInterface a clase, de repente compila
public class IInterface { } public class Class<T> where T : IInterface { public void Do() { IEnumerable<IInterface> ret = GetEnumerable(); } public IEnumerable<T> GetEnumerable() { return new T[0]; } }Sé que puedo usar:
IEnumerable<IInterface> ret = (IEnumerable<IInterface>)GetEnumerable();pero realmente me gustaría saber la razón por la cual el elenco es necesario si IInterface es una interfaz.
La verdadera pregunta es, ¿es realmente necesario?
T , en este caso específico, siempre debe ser una clase.
Puede asegurarse de ello agregando adicionalmente la restricción class .
public interface IInterface { bool Foo { get; set; } } public class Class<T> where T : class, IInterface { public void Do() { var ret = GetEnumerable(); foreach (var item in ret) { item.Foo = true; // you can handle the object just if you would have an object of that type. } } public IEnumerable<T> GetEnumerable() { return new T[0]; } } Ahora, si elimina la restricción de clase, aún funcionaría. Sin embargo, si pasa el cursor sobre los garabatos de ese item.Foo = true , se hará evidente por qué:
Como se indica en la documentación :
La variación se aplica solo a los tipos de referencia; si especifica un tipo de valor para un parámetro de tipo variante, ese parámetro de tipo es invariable para el tipo construido resultante.
Con su ejemplo de interfaz, no existe tal restricción en T , mientras que con el ejemplo de clase se infiere esta restricción.
Si necesita restringir a una interfaz, se requiere una "restricción de tipo de referencia" adicional:
public class Class<T> where T : class, IInterface