14

ネストされたクラスのクラスの拡張機能を記述するのは便利/論理的だと思います。主な理由は、単にそのクラスExtensionsに名前を付けて、外側の名前付けスコープにコンパイラの一意の型名を付けることができるからです。

次のようなものを禁止する技術的な理由は何ですか:

public class Foo
{
   ObjectSet<Bar> Bars { get; set; }

   public static class Extensions
   {
      public static Bar ByName(this ObjectSet<Bar> bars, string name)
      {
         return bars.FirstOrDefault(c => c.Name == name);
      }
   }
}

今は別の独立したクラスを作成する必要があります。

更新/注:それが内部クラスであるという事実が拡張メソッドの可用性の範囲に影響を与えるとは想像していませんでした。私は、別の名前を持つ別のクラスで実用的なコーディングの問題に対処したかっただけです。

4

3 に答える 3

8

ここで重要な点は、ネストされたクラスが外部クラスのプライベート フィールドにアクセスできることです

したがって、次のコードが機能します。

public class Foo
{
    private bool _field;

    public static class Extensions
    {
        public static bool GetField(Foo foo)
        {
            return foo._field;
        }
    }
}

ここでは、クラスのインスタンスを明示的に渡しています。静的メソッドはプライベート フィールドにアクセスできます...合理的です。

bool fieldValue = Foo.Extensions.GetField(new Foo());

ただし、拡張メソッドは静的メソッドの代替構文にすぎませんが、非静的インスタンス メソッドと同じ方法で呼び出されます。

ネストされたクラスで拡張メソッドが許可されている場合、それらは実際にプライベート フィールドにアクセスでき、インスタンス メソッドに非常に近くなります。これにより、意図しない結果が生じる可能性があります。

要約すると、これが許可された場合:

public class Foo
{
    private bool _field;

    public static class Extensions
    {
        public static bool GetField(*this* Foo foo) // not allowed, compile error.
        {
            return foo._field;
        }
    }
}

次に、次のコードを記述して、拡張メソッドを本来よりもインスタンス メソッドのように動作させることができます。

var foo = new Foo();
var iGotAPrivateField = foo.GetField();

コメントの結果として編集

拡張メソッドがインスタンス メソッドと同等であることがなぜ悪い考えなのですか?

Eric Lippert の言葉(強調は私のもの) :

そうです、「拡張メソッドはオブジェクト指向ではない」というよく耳にする批判は完全に正しいですが、むしろ無関係でもあります。拡張メソッドは確かにオブジェクト指向ではありません。データを操作するコードをデータを宣言するコードから遠く離れた場所に配置し、カプセル化を破ることができず、メソッドであると思われるオブジェクトのプライベートな状態と対話することができず、継承をうまく処理できません。これらは、便利なオブジェクト指向のドレスを着た手続き型プログラミングです。

于 2012-08-20T12:39:57.277 に答える
2

技術的な理由はありません - 実用的なだけです。スコープが 1 つのクラスに限定されている拡張メソッドがある場合は、それをクラスの通常の静的メソッドとして定義し、「this」を削除します。拡張機能は、複数のクラスで共有するためのものです。

于 2012-07-12T01:25:36.813 に答える
1

このことを禁止する背後にある考え方は、拡張メソッドが名前空間全体のすべてのエンティティに適用されるためだと思います。

ネストされた拡張メソッド クラスを作成する場合は、ネストされているクラスにのみ適用されます。その場合、拡張メソッドを作成する意味はありません。その後、通常の非拡張メソッドで十分です。

于 2012-07-12T01:24:32.333 に答える