En C#, si tengo un parámetro para una función donde el tipo de parámetro es de una interfaz, ¿cómo paso un objeto que implementa la interfaz?
Aquí hay un ejemplo:
El parámetro de una función es el siguiente:
List<ICustomRequired>
La lista que ya tengo es la siguiente:
List<CustomObject> exampleList
CustomObject
hereda de la interfaz ICustomRequired
¿Cuál es la sintaxis correcta para pasar la lista de exampleList
como parámetro?
Así es como pensé en hacer la tarea anterior:
exampleList as List<ICustomRequired>
Sin embargo, recibo el siguiente error:
No se puede convertir el tipo a través de una conversión de referencia, conversión boxing, conversión unboxing, conversión wrapping o conversión de tipo nulo
Gracias
No puede convertir una List
de un tipo en una List
de un tipo diferente.
Y si lo piensas, te alegrarás de no poder hacerlo. Imagina los estragos que podrías causar si fuera posible:
interface ICustomRequired { } class ImplementationOne : ICustomRequired { } class ImplementationTwo: ICustomRequired { } var listOne = new List<ImplementationOne>(); var castReference = listOne as List<ICustomRequired>(); // Because you did a cast, the two instances would point // to the same in-memory object // Now I can do this.... castReference.Add(new ImplementationTwo()); // listOne was constructed as a list of ImplementationOne objects, // but I just managed to insert an object of a different type
Tenga en cuenta, sin embargo, que esta línea de código es legal:
exampleList as IEnumerable<ICustomRequired>;
Esto sería seguro, porque IEnumerable
no le proporciona ningún medio para agregar nuevos objetos.
IEnumerable<T>
en realidad se define como IEnumerable<out t>
, lo que significa que el parámetro de tipo es Covariant .
¿Puede cambiar el parámetro de la función a IEnumerable<ICustomRequired>
?
De lo contrario, su única opción será crear una nueva Lista.
var newList = (exampleList as IEnumerable<ICustomRequired>).ToList();
o
var newList = exampleList.Cast<ICustomRequired>().ToList();
No puedes hacer eso, tienes que convertir la lista
exampleList.Cast<ICustomRequired>().ToList();
Además de List.Cast
, los genéricos de C# brindan un buen soporte para Covariance y contravariance . Este ejemplo hace que funcione de la manera que creo que originalmente pretendías.
public class Program { public static void Main() { Foo(new List<Fim>()); } public static void Foo<T>(List<T> bar) where T : IFim { throw new NotImplementedException(); } public class IFim{} public class Fim : IFim{} }