非表示に関して、C#の「新しい」修飾子の実用的な用途は何ですか?


21

同僚と私はnew、隠蔽の概念に適用されるC#のキーワードの動作を見ていました。ドキュメントから:

新しい修飾子を使用して、基本クラスから継承されたメンバーを明示的に非表示にします。継承されたメンバーを非表示にするには、同じ名前を使用して派生クラスで宣言し、新しい修飾子で変更します。

ドキュメントを読み、基本的に何をするのか、どのように行うのかを理解しています。本当に手に入れることができなかったのは、最初にそれを行う必要がある理由です。修飾子は2003年から存在しており、私たち2人はそれよりも長い間.Netを使用してきました。

この動作が実用的な意味で必要になるのはいつですか(例:ビジネスケースに適用される場合)。これは、その有用性よりも長持ちした機能ですか、それとも私たちがやっていること(具体的には、WebフォームとMVCアプリケーション、およびいくつかの小さな要素のWinFormsとWPF)であまり一般的ではありませんか?このキーワードを試してみて、それを試してみたところ、誤用されると少し危険に思える動作が見つかりました。

これは少し無制限に聞こえますが、この特定のツールが有用であるとわかるビジネスアプリケーションに適用できる特定のユースケースを探しています。


9
多分あなたもそれを読んだかもしれませんが、メソッド隠蔽がC#に追加された理由に関するEric Lippert(C#コンパイラ開発者)からの興味深い記事があります:blogs.msdn.com/b/ericlippert/archive/2008/05/21/…。それはあなたの質問の一部に答えますが、私はあなたのために準備ができているビジネスケースを持っていませんので、私はそれをコメントに入れます。
ジャレイン

3
@Jalayn:ビジネスケースはこの投稿でEricによって議論されています:blogs.msdn.com/b/ericlippert/archive/2004/01/07/…–
ブライアン

回答:


22

これを使用して、戻り値のタイプの共分散を模倣できます。 エリック・リッパートの説明。エリックはこのサンプルコードを提供します:

abstract class Enclosure
{
    protected abstract Animal GetContents();
    public Animal Contents() { return this.GetContents(); }
}
class Aquarium : Enclosure
{
    public new Fish Contents() { ... }
    protected override Animal GetContents() { return this.Contents(); }
}

これは回避策です。 public override Fish Contents() { ... }安全であるにもかかわらず、合法ではありません。

一般に、メソッドの非表示はクラスのコンシューマーを混乱させるため、使用しないでください(上記の特定の例はこの問題の影響を受けません)。既存のメソッドをオーバーライドしたくない場合は、新しいメソッドに別の名前を付けてください。

メソッドの非表示が必要になる可能性が高い現実の状況は、基本クラスのプロバイダーが派生クラスに既に追加したジェネリックメソッドを追加した場合です。このようなプログラムは、新しいキーワードなしでコンパイル(および警告)しnewますが、「このメソッドの私のバージョンが基本クラスのバージョンを置き換えていることを知っています。これは恐ろしくて混乱しますが、私たちはそれで立ち往生しています」派生クラスにメソッドの名前を強制的に変更するよりも、依然として優れています。

派生メソッドをオーバーライドとして扱うことを許可すると、問題が発生します。コンパイラの実装に関する懸念を無視すると、新しいメソッドは基本メソッドと意味的に異なりますが、ポリモーフィズムにより、同じ名前のメソッドを呼び出すように求められたときに新しいメソッドが呼び出されます。

この状況については、Eric Lippert がこの投稿で詳しく説明しています。


1
new「これは恐ろしくて混乱している」ためのマーカーであるため+1 。
アヴナーシャハルカシュタン

Ericの例は、私が同様の状況にあるという理由だけで非常に役立つと思います。この場合、それは必要な悪のように感じます。
カイルバラン14年

4

言語設計者が考えもしなかったことをするために必要な場合に備えて、そこにあると思います。C#は、多くの点でJavaの初期バージョンに対する反応でした。そして、javaがやったことの1つは、開発者が足を踏み入れる可能性を排除するために、開発者を非常に明確にピジョンホールで開発することでした。C#はわずかに異なるアプローチを採用しており、開発者が足を踏み入れるチャンスをさらにいくつか得られるように、開発者にもう少し力を与えました。1つの例はunsafeキーワードです。このnewキーワードは別です。

おそらく、それはおそらくそれほど有用ではありませんunsafeが、一度言語仕様に慣れると、言語仕様から抜け出すことは困難です。


5
Javaはすべてのメソッドを仮想として扱うため、Javaには新しいものがありません。エリックリッパートによると、新しいサポートの動機は、脆弱な基本クラスの問題を解決することです。newの存在は、低レベルのライブラリーの使用だけでなく、実際のビジネスでの使用にも必要です。Javaに新しい(および非仮想メソッドがない)が存在するということは、基本クラスが派生クラス内で既に使用されている新しいメソッドを導入すると、基本クラスの開発者が許可されるべきにもかかわらず、既存のコードが破損する可能性があることを意味しますそれを消費するコードを忘れる。
ブライアン

3

誤ってではなく、「意図的にこのメソッドの基本クラスの実装を隠した」と読者に伝えています。


5
これは質問を懇願するように私を打つ。OPは、何をするのかを知っていますが、その理由を知りたいです。
ブライアン

0

前のメンバーを別の名前で利用できるようにすることもできます。

class VehicleClass
{
  public int AnyProperty
  {
    get; set;
  }

  public int AnyFunction() { return 0; }
} // VehicleClass

class IntermediateClass : VehicleClass
{
  public int PreviousAnyProperty
  {
    get { return AnyProperty; }
    set { AnyProperty = value  }
  }

  public int PreviousAnyFunction() { return AnyFunction(); }
} // IntermediateClass 

class CarClass : IntermediateClass
{
  public new int AnyProperty
  {
    get ; set ;
  }

  public new int AnyFunction() { return 5; }
} // class CarClass

class ExampleClass
{

  public static void Main()
  {
    using (CarClass MyCar = new CarClass())
    {
      int AnyInt1 = MyCar.PreviousAnyProperty;
      MyCar.PreviousAnyProperty = 7;

      int AnyInt2 = MyCar.PreviousAnyFunction();

      int AnyInt3 = MyCar.AnyProperty;
      MyCar.AnyProperty = 45;

      int AnyInt4 = MyCar.AnyFunction();
    }
  } // static void Main()

} // class CarClass

乾杯。


私はそれがどのように動作するかに精通んだけど、本当に私の質問は、なぜあなたは別の名前を介して利用可能な前のメンバーを持つようにしたいですか?これは、あらゆる種類の契約を破り、特定の汎用部分を役に立たなくします。
ジョエルイーサートン

@Joel Etherton:ご存じのとおり、開発者はコードをプログラミングする他の人を「選ぶ」必要がある場合があります。また、クラスを変更したり、拡張したりする権限がない場合があります。また、前のメンバーと新しいメンバーの両方を使用する必要がある場合があります。
umlcat

0

レガシコードのテストスイートを作成する場合、非常に便利です。他のメソッドで使用されるメソッド内のデータベースを照会するなど、外部の依存関係を隠すことができます。他のメソッドをテストできるように、テストクラスのメソッドに仮想キーワードを追加する必要なく、外部リソースに依存する元のロジックを非表示にできます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.