2012-02-08 22 views
15

Tengo dos opciones en VS2010 para implementar interfaces.Interfaz de implementación frente a interfaz de implementación explícitamente en C#

enter image description here

Cuando tengo interfaz IHelper.cs de la siguiente manera:

public interface IHelper 
    .... 
    IEnumerable<IPort> Ports { get; } 

"Implementar interfaz explícitamente" da este código:

IEnumerable<IPort> IHelper.Ports 
    { 
     get 
     { 
      ... 
     } 
    } 

Y, "Implementar interfaz" me da este código:

public IEnumerable<IPort> Ports 
    { 
     get 
     { 
      ... 
     } 
    } 

¿Son iguales o diferentes? ¿Por qué tengo dos opciones para implementar interfaces en C#?

+0

¿Habría sido "Implementar interfaz pública" e "Implementar interfaz privada" demasiado difíciles? – PRMan

Respuesta

24

Las declaraciones explícitas de interfaz significan que los miembros de la interfaz no están disponibles en otros tipos de interfaz, por lo que los tipos de implementación deberían enviarse a la interfaz antes de acceder a ellos públicamente.

Implícita, la forma estándar en que se implementan la mayoría de las interfaces, expone los elementos de la interfaz en la API pública del tipo implementador.

La razón principal para las definiciones de interfaz explícita es evitar conflictos de nombres si implementa dos interfaces que contienen métodos con la misma firma ... la definición explícita permite que el compilador mantenga las firmas lo suficientemente claras como para resolverlas.

Una razón secundaria que admite el mantenimiento de código, como lo sugiere XenoPuTtSs en los comentarios, es que las definiciones explícitas desencadenarán errores de compilación en los tipos de implementación si se elimina la firma del método. En las implementaciones implícitas, eliminar un método de la interfaz dejará el método como un miembro regular de cualquier tipo, lo que significa que debe buscar manualmente las implementaciones de métodos que ya no se ejecutan.

+2

también (que no es una razón principal) cuando la interfaz cambia (como un método se elimina o cambia) el compilador lanzará un error en las clases que explícitamente definen interfaces porque esos métodos ya no están en la interfaz. Esta es una forma útil (en mi humilde opinión) para localizar el código no utilizado de proyectos grandes. – XenoPuTtSs

+0

@XenoPuTtSs Buen punto, he modificado mi respuesta para incluir esto. –

5

Una clase que implementa una interfaz puede implementar explícitamente un miembro de esa interfaz. Cuando un miembro se implementa explícitamente, no se puede acceder a través de una instancia de clase, sino solo a través de una instancia de la interfaz.

// explicit1.cs 
interface IDimensions 
{ 
    float Length(); 
    float Width(); 
} 

class Box : IDimensions 
{ 
    float lengthInches; 
    float widthInches; 

public Box(float length, float width) 
{ 
    lengthInches = length; 
    widthInches = width; 
} 
// Explicit interface member implementation: 
float IDimensions.Length() 
{ 
    return lengthInches; 
} 
// Explicit interface member implementation: 
float IDimensions.Width() 
{ 
    return widthInches;  
} 

public static void Main() 
{ 
    // Declare a class instance "myBox": 
    Box myBox = new Box(30.0f, 20.0f); 
    // Declare an interface instance "myDimensions": 
    IDimensions myDimensions = (IDimensions) myBox; 
    // Print out the dimensions of the box: 
    /* The following commented lines would produce compilation 
    errors because they try to access an explicitly implemented 
    interface member from a class instance:     */ 
    //System.Console.WriteLine("Length: {0}", myBox.Length()); 
    //System.Console.WriteLine("Width: {0}", myBox.Width()); 
    /* Print out the dimensions of the box by calling the methods 
    from an instance of the interface:       */ 
    System.Console.WriteLine("Length: {0}", myDimensions.Length()); 
    System.Console.WriteLine("Width: {0}", myDimensions.Width()); 
} 
} 

aplicación explícita de interfaces también permite al programador heredan dos interfaces que comparten los mismos nombres de los miembros y dar a cada miembro de interfaz de una aplicación separada. Este ejemplo muestra las dimensiones de un cuadro en unidades métricas e inglesas. La clase Box hereda dos interfaces, IEnglishDimensions e IMetricDimensions, que representan los diferentes sistemas de medición. Ambas interfaces tienen nombres de miembros idénticos, Longitud y Ancho.

vistazo al ejemplo

// explicit2.cs 
// Declare the English units interface: 
interface IEnglishDimensions 
{ 
    float Length(); 
    float Width(); 
} 
// Declare the metric units interface: 
interface IMetricDimensions 
{ 
    float Length(); 
    float Width(); 
} 
// Declare the "Box" class that implements the two interfaces: 
// IEnglishDimensions and IMetricDimensions: 
class Box : IEnglishDimensions, IMetricDimensions 
{ 
    float lengthInches; 
    float widthInches; 
public Box(float length, float width) 
    { 
    lengthInches = length; 
    widthInches = width; 
    } 
// Explicitly implement the members of IEnglishDimensions: 
float IEnglishDimensions.Length() 
{ 
    return lengthInches; 
} 
float IEnglishDimensions.Width() 
{ 
    return widthInches;  
} 
// Explicitly implement the members of IMetricDimensions: 
float IMetricDimensions.Length() 
{ 
    return lengthInches * 2.54f; 
} 
float IMetricDimensions.Width() 
{ 
    return widthInches * 2.54f; 
} 
public static void Main() 
{ 
    // Declare a class instance "myBox": 
    Box myBox = new Box(30.0f, 20.0f); 
    // Declare an instance of the English units interface: 
    IEnglishDimensions eDimensions = (IEnglishDimensions) myBox; 
    // Declare an instance of the metric units interface: 
    IMetricDimensions mDimensions = (IMetricDimensions) myBox; 
    // Print dimensions in English units: 
    System.Console.WriteLine("Length(in): {0}", eDimensions.Length()); 
    System.Console.WriteLine("Width (in): {0}", eDimensions.Width()); 
    // Print dimensions in metric units: 
    System.Console.WriteLine("Length(cm): {0}", mDimensions.Length()); 
    System.Console.WriteLine("Width (cm): {0}", mDimensions.Width()); 
} 
} 

para más detalles mira esto article

+1

Lo mejor es incluir las piezas relevantes de información del artículo en la respuesta en sí, los enlaces son caprichosos y pueden no durar tanto tiempo como la respuesta. Si ese enlace fallara, su respuesta no proporcionaría ninguna ayuda. –

+0

sí agregué contigo. – Serghei

6

Ellos son totalmente diferentes. Si implementa interfaces explícitamente, podrá hacer referencia a los miembros de la interfaz solo por referencia de esa interfaz. El siguiente código demuestra la idea.

public interface IFoo { 
    String Bar { get; set; } 
} 
public class ImplicitFoo : IFoo { 
    public string Bar {get;set;} 
} 
public class ExplicitFoo : IFoo { 
    private String _Bar; 
    string IFoo.Bar { 
     get { 
      return _Bar; 
     } 
     set { 
      _Bar = value; 
     } 
    } 
} 
public class Test { 
    public void Test() { 
     var iml = new ImplicitFoo(); 
     // Works fine 
     Console.WriteLine(iml.Bar); 
     var expl = new ExplicitFoo(); 
     var fooInterface = (IFoo)expl; 
     // Works fine 
     Console.WriteLine(fooInterface.Bar); 
     // Throws compile time exception 
     Console.WriteLine(expl.Bar); 
    } 
} 
Cuestiones relacionadas