2017-03-30 4 views
6

私たちはC#でプロパティを使用する場合、コンパイラは常にMSIL(すなわち、get_PropertyNameとset_PropertyName)でそれらのgetterとsetterを生成することを知って、例えば、次のコードを考えてみます。C#のプロパティには、常に「バックグラウンド」のバックアップフィールドがありますか?

class Program 
    { 
     class Test 
     { 
      public string Name { get; set; } 
     } 
     static void Main(string[] args) 
     { 
      //Here I'm using reflection to inspect methods of Test class 
      Type type = typeof(Test); 
      foreach (var item in type.GetMethods()) 
      { 
       Console.WriteLine(item.Name); 
      } 
     } 
    } 

このプログラムTestの方法で出力を生成します。その中には、get_Nameset_Nameがあります。これは私が言っていたゲッターとセッターです。 gettersとsetterが "舞台裏で"作成された場合、ゲッターとセッターが取得/設定する値を取得するバックアップフィールドも作成する必要があります。 ので、前の例から、私はそのように、Testクラスのフィールドを検査するためにリフレクションを使用することができます。

static void Main(string[] args) 
    { 
     Type type = typeof(Test); 
     foreach (var item in type.GetFields()) 
     { 
      Console.WriteLine(item.Name); 
     } 
    } 

このプログラムの出力に含まは空で、私が作成されたバックアップフィールドはprivateを持っているためであると仮定アクセスできないので見えません。しかし、私はそれをチェックする方法がわからないので、バックアップフィールドが常に作成された場合にお知らせください(get;とという単純なプロパティを持っていても)。

+0

私が知っている限り、彼らはそうしています。 – Alex

+5

他の参考資料も簡単に見つけることができます。これらは通常、バックアップフィールドではなく、*バッキング*フィールドとして知られています。 –

+0

C#のそれ以降のバージョンで追加された機能が、主な用途を隠してしまったことは面白いです。 – IllidanS4

答えて

13

あなたのような単純なプロパティを意味する場合:

{get;set;} 

か:

{get;} 

を[はい、フィールドがあります。あなたのGetFields()コールにBindingFlags.NonPublic | BindingFlags.Instanceを追加し、あなたはそれが表示されます:

foreach (var item in type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)) 
{ 
    Console.WriteLine(item.Name); 
} 

それは通常<>を含むunpronouncable名前を持っている - あなたは私のマシン上で<Name>k__BackingFieldである - しかし:この名前は、コンパイラの機能です(連載の多くが、 etcライブラリはそれを利用するので、変更することはほとんどありません)。

しかし、いいえ、プロパティはありませんそれ自身では常にフィールドを含みます。例えば:

public int Value => 42; // no field 

または

public int Name { get { return obj.Name; } set { obj.Name = value; } } 
13

しかし、私はそれを確認する方法がわからないので、あなたは私たちが持っていても(バックアップフィールドは常に作成されます場合は私に知らせてくださいすることができます設定;;のみを取得して、単純なプロパティ?

は自動的に、例えば

プロパティを実装
public int ReadWriteProperty { get; set; } 
public int ReadOnlyProperty { get; } 

実際には常にコンパイラーによって生成されたバッキングフィールドがあります。しかし、あなたはゲッター/セッターの独自の実装を提供する場合、コンパイラはフィールドを生成しません。

public int Zero => 0; 

public int IgnoresSetter 
{ 
    get { return 10; } 
    set { /* Meh. Whatever you say, I'm still going to return 10 in the getter... */ } 
} 

それらのどちらもフィールドが生成されます。

関連する問題