utilizar usar usan una que programacion porque orientada objetos las interfaz interfaces implementacion ejemplos definicion como c# class interface

c# - usan - ¿Por qué no puedo usar un tipo concreto compatible al implementar una interfaz?



porque usar interfaces c# (3)

Me gustaría poder hacer algo como esto:

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Test { public interface IFoo { IEnumerable<int> integers { get; set; } } public class Bar : IFoo { public List<int> integers { get; set; } } }

¿Por qué el compilador se queja ...?

Error 2 ''Test.Bar'' does not implement interface member ''Test.IFoo.integers''. ''Test.Bar.integers'' cannot implement ''Test.IFoo.integers'' because it does not have the matching return type of ''System.Collections.Generic.IEnumerable<int>''.

Entiendo que la interfaz dice IEnumerable y la clase usa una lista, pero una lista es un IEnumerable .....

¿que puedo hacer? No quiero especificar IEnumerable en la clase, quiero usar un tipo concreto que implemente IEnumerable, como List ...


Aunque List implementa IEnumerable, esa no es la forma en que funcionan las interfaces. La interfaz especifica exactamente qué tipos necesitan estar expuestos para las propiedades. Si creó una interfaz genérica como

public interface IFoo<T> where T : IEnumerable<int> { T integers { get; set; } }

Luego puede usar IFoo<List<int>> para implementarlo de la manera que espera.


Este es un problema de tipo Covarianza / Contravarianza (ver http://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)#C.23 ).

Hay una solución alternativa: use interfaces explícitas, como las siguientes:

public class Bar : IFoo { private IList<int> _integers; IEnumerable<int> IFoo.integers { get { return _integers }; set { _integers = value as IList<int>; } } public IList<int> integers { get { return _integers; } set { _integers = vale; } } }

Tenga en cuenta que los integers deben ser TitleCased para ajustarse a las pautas de .NET.

Con suerte, puede ver el problema en el código anterior: IList<int> es compatible con IEnumerable<int> solo para el IEnumerable<int> acceso, pero no para la configuración. ¿Qué sucede si alguien llama a IFoo.integers = new Qux<int>() (donde Qux : IEnumerable<int> pero no Qux : IList<int> ).


No podrá usar un tipo concreto a menos que lo haga detrás de escena. El problema es que puedes obtener y establecer la propiedad.

Su interfaz especifica que la propiedad es de tipo IEnumerable<int> . HashSet<int> implementa IEnumerable<int> . Eso significa que lo siguiente debería funcionar bien:

IFoo instance = new Bar(); instance.integers = new HashSet<int>();

Pero como intenta implementar la interfaz con el tipo concreto List<int> , no hay forma de que la asignación pueda funcionar.

La solución más sencilla, suponiendo que no necesite volver a asignar la colección constantemente, sería especificar solo un getter para la colección:

public interface IFoo { IEnumerable<int> Integers { get; } } public class Bar { public List<int> Integers { get; private set; } public Bar(List<int> list) { Integers = list; } }