¿Está permitido usar una implementación de interfaz explícita para ocultar miembros en C #?

13

Comprendo cómo trabajar con interfaces y la implementación de interfaces explícitas en C #, pero me preguntaba si se considera una mala forma para ocultar ciertos miembros que no se usarían con frecuencia. Por ejemplo:

public interface IMyInterface
{
    int SomeValue { get; set; }
    int AnotherValue { get; set; }
    bool SomeFlag { get; set; }

    event EventHandler SomeValueChanged;
    event EventHandler AnotherValueChanged;
    event EventHandler SomeFlagChanged;
}

Sé de antemano que los eventos, aunque son útiles, rara vez se utilizarán. Por lo tanto, pensé que tendría sentido esconderlos de una clase de implementación a través de una implementación explícita para evitar el desorden de IntelliSense.

    
pregunta Kyle Baran 27.10.2014 - 21:42

4 respuestas

39

Sí, generalmente es una mala forma.

  

Por lo tanto, pensé que tendría sentido esconderlos de una clase implementadora a través de una implementación explícita para evitar el desorden de IntelliSense.

Si su IntelliSense está demasiado abarrotado, su clase es demasiado grande. Si su clase es demasiado grande, es probable que esté haciendo demasiadas cosas o que esté mal diseñado.

Solucione su problema, no su síntoma.

    
respondido por el Telastyn 27.10.2014 - 21:58
11

Usa la función para lo que fue diseñada. Reducir el desorden de espacio de nombres no es uno de esos.

Las razones legítimas no se refieren a la "ocultación" u organización, sino a la ambigüedad y la especialización. Si implementa dos interfaces que definen "Foo", la semántica para Foo podría diferir. Realmente no hay una mejor manera de resolver esto, excepto las interfaces explícitas. La alternativa es no permitir la implementación de interfaces superpuestas, o declarar que las interfaces no pueden asociar la semántica (que de todos modos es solo una cosa conceptual). Ambas son malas alternativas. A veces la practicidad triunfa sobre la elegancia.

Algunos autores / expertos lo consideran un conjunto de características (los métodos no son realmente parte del modelo de objetos del tipo). Pero como todas las funciones, en algún lugar, alguien lo necesita.

Una vez más, no lo usaría para ocultar u organizar. Hay formas de ocultar a los miembros de intellisense.

[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
    
respondido por el codenheim 27.10.2014 - 22:07
5

Podría ser un signo de código desordenado, pero a veces el mundo real es desordenado. Un ejemplo de .NET framework es ReadOnlyColection que oculta la mutación setter [], Add and Set.

I.E ReadOnlyCollection implementa IList < T & gt ;. Vea también mi pregunta para TAN hace varios años cuando me lo planteé.

    
respondido por el Esben Skov Pedersen 27.10.2014 - 22:00
2

Es una buena forma de hacerlo cuando el miembro no tiene sentido en contexto. Por ejemplo, si crea una colección de solo lectura que implementa IList<T> delegando a un objeto interno _wrapped , entonces podría tener algo como:

public T this[int index]
{
  get
  {
     return _wrapped[index];
  }
}
T IList<T>.this[int index]
{
  get
  {
    return this[index];
  }
  set
  {
    throw new NotSupportedException("Collection is read-only.");
  }
}
public int Count
{
  get { return _wrapped.Count; }
}
bool ICollection<T>.IsReadOnly
{
  get
  {
    return true;
  }
}

Aquí tenemos cuatro casos diferentes.

public T this[int index] está definido por nuestra clase en lugar de la interfaz, y por lo tanto, por supuesto no es una implementación explícita, aunque tenga en cuenta que es similar a la lectura-escritura T this[int index] definida en la interfaz, pero se lee -sólo.

T IList<T>.this[int index] es explícito porque una parte de él (el captador) se corresponde perfectamente con la propiedad anterior, y la otra parte siempre lanzará una excepción. Si bien es vital para alguien que accede a una instancia de esta clase a través de la interfaz, no tiene sentido que alguien lo use a través de una variable del tipo de la clase.

De manera similar, porque bool ICollection<T>.IsReadOnly siempre devolverá verdadero, no tiene ningún sentido el código escrito contra el tipo de clase, pero podría ser vital para usarlo a través del tipo de interfaz y, por lo tanto, lo implementamos explícitamente.

Por el contrario, public int Count no se implementa explícitamente porque podría ser útil para alguien que usa una instancia a través de su propio tipo.

Pero con su caso "muy poco utilizado", me inclinaría por no usar una implementación explícita.

En los casos en los que recomiendo usar una implementación explícita que llame al método a través de una variable del tipo de clase sería un error (intentar usar el establecedor indexado) o inútil (verificar un valor que siempre será el mismo) por lo tanto, al esconderlos, está protegiendo al usuario de un código defectuoso o subóptimo. Eso es significativamente diferente al código que cree que es muy probable que se utilice rara vez . Para eso, podría considerar usar el atributo EditorBrowsable para ocultar el miembro de intellisense, aunque incluso de eso estaría cansado; los cerebros de las personas ya tienen su propio software para filtrar lo que no les interesa.

    
respondido por el Jon Hanna 28.10.2014 - 14:13

Lea otras preguntas en las etiquetas