web-dev-qa-db-ja.com

C#でメンバーを非表示にする明示的なインターフェイス実装を使用することは許可されますか?

C#でのインターフェイスと明示的なインターフェイスの実装の操作方法は理解していますが、頻繁に使用されない特定のメンバーを非表示にするのが悪い形と見なされているのではないかと思っていました。例えば:

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

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

このイベントは役に立つものの、使用されることはほとんどありません。したがって、IntelliSenseの混乱を避けるために、明示的な実装を介して実装クラスからそれらを隠すことが理にかなっていると思いました。

14
Kyle Baran

はい、それは一般的に悪い形です。

したがって、IntelliSenseの混乱を避けるために、明示的な実装を介して実装クラスからそれらを隠すことが理にかなっていると思いました。

IntelliSenseが乱雑である場合、クラスが大きすぎます。クラスが大きすぎると、多くのことを実行したり、設計が不十分になったりする可能性があります。

症状ではなく、問題を修正してください。

39
Telastyn

それが意図された目的のために機能を使用してください。名前空間の混乱を減らすことは、それらの1つではありません。

正当な理由は「隠す」ことや組織に関することではなく、あいまいさを解決して専門化することです。 「Foo」を定義する2つのインターフェースを実装すると、Fooのセマンティクスが異なる場合があります。明示的なインターフェースを除いて、これを解決するより良い方法は本当にありません。もう1つの方法は、重複するインターフェースの実装を許可しないか、またはインターフェースがセマンティクスを関連付けることができないことを宣言することです(これはとにかく概念的なものです)。どちらも貧しい選択肢です。時々実用性は優雅さを上回ります。

一部の作成者/専門家は、それを機能の欠点だと考えています(メソッドは、実際には型のオブジェクトモデルの一部ではありません)。しかし、すべての機能と同様に、どこかで誰かがそれを必要としています。

繰り返しますが、私はnotを使用して、非表示または整理を行います。メンバーをインテリセンスから隠す方法があります。

[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
11
codenheim

私は乱雑なコードの兆候かもしれませんが、現実の世界は乱雑である場合があります。 .NETフレームワークの1つの例は ReadOnlyColection です。これは、変化するセッター[]、追加、設定を非表示にします。

I.E ReadOnlyCollectionはIList <T>を実装します。参照 私の質問 to SO数年前に私がこれを考えたとき。

5

メンバーが文脈上無意味であるときにそうするのは良い形です。たとえば、内部オブジェクトIList<T>に委任することによって_wrappedを実装する読み取り専用コレクションを作成する場合、次のようなものになります。

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;
  }
}

ここには4つの異なるケースがあります。

public T this[int index]はインターフェースではなくクラスによって定義されているため、明示的な実装ではありませんが、インターフェースで定義されている読み書きT this[int index]と似ていることに注意してください。読み取り専用。

T IList<T>.this[int index]は、その一部(ゲッター)が上記のプロパティと完全に一致し、他の部分は常に例外をスローするため、明示的です。インターフェースを介してこのクラスのインスタンスにアクセスするユーザーにとって不可欠ですが、クラスのタイプの変数を通じてそれを使用するユーザーにとっては無意味です。

同様に、bool ICollection<T>.IsReadOnlyは常にtrueを返すため、クラスの型に対して書き込まれたコードにはまったく意味がありませんが、インターフェイスの型を介してそれを使用するために不可欠である可能性があるため、明示的に実装します。

逆に、public int Countは明示的に実装されていません。独自の型を介してインスタンスを使用しているユーザーが使用する可能性があるためです。

しかし、「非常にまれにしか使用されない」ケースでは、明示的な実装を使用しないことに非常に強く傾くでしょう。

クラスの型の変数を介してメソッドを呼び出す明示的な実装を使用することをお勧めする場合、エラー(インデックス付きセッターを使用しようとする)または無意味(常に同じ値をチェックする)になるため、非表示にするそれらは、バグのあるコードまたは最適ではないコードからユーザーを保護しています。これはまれにが使用される可能性が高いと考えるコードとはかなり異なります。そのため、EditorBrowsable属性を使用してメンバーをインテリセンスから隠すことを検討するかもしれませんが、それでも私はうんざりするでしょう。人々の脳はすでに、彼らが興味のないものを取り除くための独自のソフトウェアを持っています。

2
Jon Hanna