¿Cuáles son algunas ventajas de usar una interfaz en C #?

Me obligaron a participar en un proyecto de software en el trabajo hace unos años, y me vi obligado a aprender C # rápidamente. Mi fondo de progtwigción es débil (ASP clásico).

He aprendido bastante a lo largo de los años, pero debido a la naturaleza forzada de cómo aprendí C #, hay muchos conceptos básicos sobre los que no estoy claro.

En concreto, una interfaz. Entiendo lo básico, pero cuando escribo una aplicación, me resulta difícil descubrir el uso práctico de una. ¿Por qué uno querría escribir una interfaz para su aplicación?

Gracias kevin

    Una interfaz dice cómo algo debería funcionar. Piense en ello como un contrato o una plantilla. Es clave para cosas como Inverson of Control o Dependancy Injection.

    Uso el mapa de estructura como mi contenedor de IoC. Esto me permite definir una interfaz para todas mis clases. Donde podrias decir

    Widget w = new Widget(); 

    yo diría

     IWidget w = ObjectFactory.GetInstance(); 

    Esto es muy poderoso ya que mi código no dice necesariamente qué es realmente un Widget. Solo sabe lo que puede hacer un Widget basado en la interfaz de IWidget.

    Esto tiene un gran poder, ya que ahora que estoy usando un contenedor IoC, puedo hacer un par de cosas más ingeniosas. En mis pruebas de unidad en las que necesito usar un Widget, puedo crear un simulacro de Widget. Entonces, digamos que mi Widget hace algo muy poderoso al conectarse a una base de datos o a un servicio web, mi simulacro puede simular la conexión a estos recursos y volver a los datos marcados. Esto hace que mi prueba se ejecute más rápido y se comporte de una manera más confiable. Debido a que estoy usando StructureMap, le puedo decir a StructureMap que cargue la implementación real de mi Widget durante el uso de producción de mi código y la versión simulada del Widget durante las pruebas programáticamente o por configuración.

    Además, debido a que estoy usando un contenedor IoC, puedo proporcionar nuevas funciones geniales a mi aplicación, como escribir tres formas diferentes de almacenar datos en caché. Puedo tener un caché de caja de desarrollador local usando una herramienta como Lucene.NET para un caché local. Puedo hacer que un servidor de desarrollo use el caché .NET que se ejecuta muy bien en una sola caja. Y luego puedo tener una tercera opción para que mis servidores de producción usen una capa de caché como MemCache Win32 o Velocity. Siempre que las tres implementaciones de almacenamiento en caché se ajusten a la misma interfaz, su implementación real no me concierne (ni a mi código) en absoluto. Simplemente le pido a StructureMap que obtenga la implementación de los entornos actuales y luego vaya a trabajar.

    Si sigues Dependency Injection, las interfaces son útiles aquí también con un contenedor IoC como StructureMap, ya que puedo declarar el uso de una clase por medio de una Interface en el constructor de mi clase.

     public class Widget(IWidgetRepository repository, IWidgetService service) : IWidget { //do something here using my repository and service } 

    Y luego, cuando hago una nueva instancia de Widget a través de StructureMap como este

     IWidget widget = ObjectFactory.GetInstance(); 

    Tenga en cuenta que no estoy especificando el repository o servicio en el constructor. StructureMap sabe a través de las interfaces especificadas en el constructor cómo obtener las instancias adecuadas y pasarlas también. Esto hace código muy potente y limpio!

    ¡Todo desde la definición simple de Interfaces y un uso inteligente de ellos!

    El caso básico es el caso “IWriter”.

    Supongamos que está creando una clase que puede escribir en la consola, y tiene todo tipo de funciones útiles, como write () y peek ().

    Luego, le gustaría escribir una clase que pueda escribir en la impresora, así que en lugar de reinventar una nueva clase, use la interfaz IWriter.

    Ahora, lo bueno de las interfaces es que puede escribir todo su código de escritura, sin saber de antemano cuál es su objective de escritura, y luego puede hacerlo cuando el usuario decide (en el tiempo de ejecución) el clima que desea escribir en la consola o la impresora, simplemente defina el objeto como un escritor de consola / impresora y no necesita cambiar nada en su código de escritura, ya que ambos usan el mismo extremo frontal (interfaz).

    Una respuesta simple: use interfaces para progtwigr contra el contrato en lugar de la implementación .

    ¿Cómo podría ayudar eso? Comenzar a usar interfaces (con suerte) te hará tener el hábito de acoplar clases de manera más relajada. Cuando codifica en contra de sus propias clases concretas, es fácil comenzar a meter las estructuras de datos sin una separación estricta de preocupaciones. Terminas con clases que “saben” todo sobre las otras clases y las cosas se pueden enredar bastante. Al limitarte a una interfaz, solo tienes la garantía de que cumple con el contrato de la interfaz. Inyecta una fricción a veces útil contra el acoplamiento apretado.

    Un ejemplo. Considere una aplicación MDI que muestre informes, básicamente hay 2 tipos de informes diferentes. Un gráfico y una cuadrícula. Necesito guardar estos informes como PDF y debo enviarlos a alguien. El controlador de eventos para el menú en el que el usuario hace clic para guardar un informe en PDF podría hacer esto:

     void ExportPDF_Clicked(...) { if(currentDocument is ChartReport) { ChartReport r = currentDocument as ChartReport; r.SavePDF(); } else if(currentDocument is GridReport) { GridReport r = currentDocument as GridReport; r.SavePDF(); } } 

    Prefiero hacer que mi ChartReport y GridReport implementen esta interfaz:

     public interface Report { void MailTo(); void SavePDF(); } 

    Ahora puedo hacer:

     void ExportPDF_Clicked(...) { Report r = currentDocument as Report; r.SavePDF(); } 

    Similar para otro código que necesita hacer la misma operación (guardarlo en un archivo, acercar, imprimir, etc.) en los diferentes tipos de informes. El código anterior aún funcionará bien cuando añada un PivotTableReport que también impulsará Rpoert la próxima semana.

    El COI y la dependency injection ya se han mencionado anteriormente, y le insto a que los mire.

    Sin embargo, en gran medida, las interfaces permiten especificar un contrato para un objeto que no requiere un modelo de herencia.

    Digamos que tengo la clase Foo, que tiene las funciones x y y y la propiedad z, y construyo mi código a su alrededor.

    Si descubro una mejor manera de hacer Foo, u otro tipo de Foo requiere implementación, puedo, por supuesto, extender una clase de Foo base a FooA, FooB, MyFoo, etc., sin embargo, eso requeriría que todos los Foos tengan la misma funcionalidad principal. o, de hecho, que los futuros creadores de Foo tengan acceso a la clase base de Foo y comprendan su funcionamiento interno. En C #, eso significaría que los futuros Foos no podrían heredar de otra cosa que no sea Foo, ya que C # no admite la herencia múltiple.

    También me exigiría estar al tanto de los posibles estados futuros de Foo y tratar de no nhibernatelos en mi clase base de Foo.

    El uso de una interfaz IFoo simplemente establece el “contrato” que requiere una clase para trabajar en mi marco de trabajo de Foo, y no me importa lo que las futuras clases de Foo puedan heredar o tener un aspecto interno, siempre que tengan fn x fn y y z. Hace un marco mucho más flexible y abierto a futuras adiciones.

    Sin embargo, si Foo requiere una gran cantidad de núcleo en su base para funcionar que no sería aplicable en un escenario de contrato, es decir, cuando se favorecería la herencia.

    Aquí hay un libro que habla de interfaces. Promueve la noción de que las interfaces pertenecen al cliente , es decir, la persona que llama. Es una buena idea. Si solo necesita lo que está llamando para implementar, digamos, count () y get (), entonces puede definir dicha interfaz y dejar que las clases implementen esas funciones. Algunas clases tendrán muchas otras funciones, pero solo te interesan esas dos, por lo que necesitas saber menos acerca de las clases con las que estás trabajando. Mientras cumplan con el contrato, puede utilizarlos.

    buen artículo.

    Una interfaz es un contrato que garantiza a un cliente cómo se comportará una clase o estructura.

    http://www.codeguru.com/csharp/csharp/cs_syntax/interfaces/article.php/c7563

    Esta podría ser la forma más clara y fácil de explicar que he encontrado:

    “La respuesta es que proporcionan un medio bastante seguro para construir rutinas que aceptan objetos cuando no conoce el tipo específico de objeto que se pasará antes de tiempo. Lo único que sabe sobre los objetos que se pasarán. Su rutina es que tienen miembros específicos que deben estar presentes para que su rutina pueda trabajar con ese objeto. El mejor ejemplo que puedo dar de la necesidad de interfaces es en un entorno de equipo. Las interfaces ayudan a definir cómo hablan los diferentes componentes. Al usar una interfaz, elimina la posibilidad de que un desarrollador malinterprete lo que los miembros deben agregar a un tipo o cómo llamarán a otro tipo que define una interfaz. Sin una interfaz, los errores se introducen en el sistema y no lo hacen. aparece hasta el tiempo de ejecución, cuando son difíciles de encontrar. Con las interfaces, los errores en la definición de un tipo se detectan de inmediato en el momento de la comstackción, donde el costo es mucho menor “.

    Un par de cosas, cuando heredas de una interfaz, te obliga a implementar todos los métodos definidos en la interfaz. Por otro lado, esta también es una buena manera de traer herencia múltiple que no es compatible con las clases regulares. http://msdn.microsoft.com/en-us/library/ms173156.aspx

    Respuesta simple basada en los primeros principios:

    Un progtwig es un universo con su propia metafísica (la realidad / sustancia / materia del código) y la epistemología (lo que puede saber / creer / razonar sobre el código). Un buen lenguaje de progtwigción intenta maximizar la flexibilidad metafísica (te permite hacer las cosas fácilmente) al tiempo que garantiza el rigor epistémico (asegura que tu universo sea coherente internamente).

    Entonces, piense en la herencia de implementación como un bloque de construcción metafísico (las cosas que conforman su pequeño universo de código) y la herencia de interfaz como una restricción epistémica (le permite creer algo acerca de su código).

    Utiliza interfaces cuando solo quiere asegurarse de poder creer algo. La mayoría de las veces eso es todo lo que necesitas.

    Mencionó que tiene dificultades para encontrar un uso práctico para las interfaces. Descubrí que surgen cuando crean aplicaciones extensibles, por ejemplo, una aplicación basada en complementos en la que un complemento de terceros debe cumplir con reglas específicas. Estas reglas pueden Ser definido por una interfaz.

    Podría hacerlo de modo que cuando se cargue el complemento, deba tener un método Init que tome una clase que implemente la interfaz IServices.

     public interface IServices { DataManager Data { get; set; } LogManager Log { get; set; } SomeOtherManager SomeOther { get; set; } } public class MrPlugin { public void Init(IServices services) { // Do stuff with services } } 

    Entonces … Si tiene una clase que implementa la interfaz IServices, y luego la crea una vez, puede pasarla a todos los complementos en el momento de la inicialización y pueden usar cualquier servicio que haya definido en la interfaz.