C# の自動プロパティで get と set の両方が必須である場合、わざわざ「get; set;」と指定する必要があるのはなぜですか。まったく?
9 に答える
読み取り専用プロパティが必要な場合があるため:
public int Foo { get; private set; }
または書き込み専用プロパティ:
public int Foo { private get; set; }
エラー: プロパティまたはインデクサーは、out または ref パラメーターとして渡されない可能性があります
指定しなかった場合{get; set;}
、コンパイラはそれがフィールドかプロパティかを認識できません。これは重要です。なぜなら、それらは同一に「見える」にもかかわらず、コンパイラーはそれらを異なる方法で扱うからです。たとえば、プロパティで "InitAnInt" を呼び出すと、エラーが発生します。
class Test
{
public int n;
public int i { get; set; }
public void InitAnInt(out int p)
{
p = 100;
}
public Test()
{
InitAnInt(out n); // This is OK
InitAnInt(out i); // ERROR: A property or indexer may not be passed
// as an out or ref parameter
}
}
クラスにパブリック フィールド/変数を作成するべきではありません。get および set アクセサーを使用するようにいつ変更する必要があるかわかりません。また、特にAPI に対してプログラムするクライアント。
また、{get; など、get と set に対して異なるアクセス修飾子を使用することもできます。private set;} は、get を public にし、set を宣言クラスに対して private にします。
このトピックに関する私の調査結果を共有すると思いました。
次のようなプロパティのコーディングは、.net 3.0 ショートカット コール「<strong>自動実装プロパティ」です。
public int MyProperty { get; set; }
これにより、入力の手間が省けます。プロパティを宣言する長い道のりは次のようになります。
private int myProperty;
public int MyProperty
{
get { return myProperty; }
set { myProperty = value; }
}
「自動実装プロパティ」を使用すると、コンパイラはコードを生成して、get と set を何らかの「k_BackingField」に関連付けます。以下は、Reflector を使用して逆アセンブルされたコードです。
public int MyProperty
{
[CompilerGenerated]
get
{
return this.<MyProperty>k__BackingField;
}
[CompilerGenerated]
set
{
this.<MyProperty>k__BackingField = value;
}
}
IL から逆アセンブルされた C# コード
また、setter と getter のメソッドを接続します。
[CompilerGenerated]
public void set_MyProperty(int value)
{
this.<MyProperty>k__BackingField = value;
}
[CompilerGenerated]
public int get_MyProperty()
{
return this.<MyProperty>k__BackingField;
}
IL から逆アセンブルされた C# コード
セッターをプライベートに設定して、読み取り専用の自動実装プロパティを宣言する場合:
public int MyProperty { get; private set; }
すべてのコンパイラは、「set」にプライベートとしてフラグを立てます。セッターとゲッターメソッドは同じことを言います。
public int MyProperty
{
[CompilerGenerated]
get
{
return this.<MyProperty>k__BackingField;
}
private [CompilerGenerated]
set
{
this.<MyProperty>k__BackingField = value;
}
}
IL から逆アセンブルされた C# コード
したがって、フレームワークが両方の get; を必要とする理由がわかりません。設定します。自動実装されたプロパティ。set および setter メソッドが提供されていなければ、それらを記述できなかった可能性があります。しかし、これを困難にするコンパイラレベルの問題があるかもしれませんが、私にはわかりません。
読み取り専用プロパティを宣言する長い道のりを見ると、次のようになります。
public int myProperty = 0;
public int MyProperty
{
get { return myProperty; }
}
次に、逆アセンブルされたコードを見てください。セッターはまったくいません。
public int Test2
{
get
{
return this._test;
}
}
public int get_Test2()
{
return this._test;
}
IL から逆アセンブルされた C# コード
プレーンフィールドと区別する方法が必要だからです。
また、さまざまなアクセス修飾子があると便利です。
public int MyProperty { get; private set; }
コンパイラは、getter や setter を生成するかどうか、またはフィールドを宣言するかどうかを知る必要があります。
プロパティにアクセサーがない場合、コンパイラはそれをフィールドからどのように分離しますか? そして、それをフィールドから分離するものは何ですか?
明らかに、フィールドとプロパティの間のあいまいさを解消する方法が必要です。しかし、必須キーワードは本当に必要なのでしょうか? たとえば、次の 2 つの宣言が異なることは明らかです。
public int Foo;
public int Bar { }
それはうまくいくかもしれません。つまり、これはおそらくコンパイラが理解できる構文です。
しかし、その後、空のブロックがセマンティックな意味を持つ状況に陥ります。それは不安定に思えます。
誰も言及していないので...自動プロパティを仮想にしてオーバーライドすることができます:
public virtual int Property { get; set; }
get/set がない場合、どのようにオーバーライドされますか? setter ではなく getterをオーバーライドできることに注意してください 。
public override int Property { get { return int.MinValue; } }