2017-03-30 93 views
6

wiem, że kiedy używamy właściwości w języku C#, kompilator zawsze wygenerowania pobierające i ustawiające dla nich w MSIL (tj get_PropertyName i set_PropertyName), na przykład, rozważmy następujący fragment kodu:Czy właściwości C# zawsze mają pola kopii zapasowych "za sceną"?

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

Ten program wytworzy wyjście za pomocą metod z Test, wśród których będą get_Name i set_Name - getter i setery, o których mówiłem. W moim rozumieniu, jeśli setery pobierające i ustawiające są tworzone "za kulisami", wówczas powinno również istnieć pole kopii zapasowej, z którego/do którego pobierają i ustawiają wartości pobierające i ustawiające. Tak, jak w poprzednim przykładzie, mogę użyć refleksji do wglądu pola dla klasy Test tak:

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

ouput tego programu jest pusta, zakładam, to dlatego, że pole kopii zapasowej utworzony ma private dostęp, więc nie możemy go zobaczyć. Ale ponieważ nie wiem, jak to sprawdzić, proszę dać mi znać, czy pole tworzenia kopii zapasowych zawsze zostanie utworzone (nawet jeśli mamy prostą właściwość z tylko get; i)?

+0

O ile wiem, że tak. – Alex

+5

Po to, aby łatwiej znaleźć inne materiały referencyjne: są one zwykle znane jako * pola * cofania *, a nie * pola kopii zapasowych *. –

+0

Zabawne, że funkcja dodana w późniejszych wersjach C# przyćmił ich główne zastosowanie. – IllidanS4

Odpowiedz

13

Jeśli masz na myśli prostych właściwości, takie jak:

{get;set;} 

lub:

{get;} 

to tak, tam jest pole; dodać BindingFlags.NonPublic | BindingFlags.Instance do rozmowy GetFields() i zobaczysz go:

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

Zwykle ma unpronouncable nazwę udziałem <> - twoja jest <Name>k__BackingField na moim komputerze - ale: Ta nazwa to cecha kompilatora (chociaż wiele z serializacji korzystają z niego biblioteki, więc jest mało prawdopodobne, aby uległy zmianie).

Ale: nie, właściwości same nie wymagają zawsze dotyczą pól; na przykład:

public int Value => 42; // no field 

lub

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

Ale ponieważ nie wiem jak to sprawdzić, czy możesz dać mi znać, jeśli pole backup zawsze uzyskać utworzone (nawet jeśli mamy prosty obiekt z tylko dostać, a ustawiony;?

automatycznie realizowane nieruchomość, np

public int ReadWriteProperty { get; set; } 
public int ReadOnlyProperty { get; } 

rzeczywiście zawsze będzie mieć pole kopii generowane przez kompilator. Ale jeśli podasz swoją realizację getter/setter, następnie kompilator nie wygeneruje pole:

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... */ } 
} 

Żadna z tych spowoduje pola mają zostać wygenerowane.