2017-03-30 20 views
6

Tôi biết rằng khi chúng ta sử dụng tài sản trong C#, trình biên dịch luôn tạo getter và setter cho họ trong MSIL (ví dụ, get_PropertyName và set_PropertyName), ví dụ, hãy xem xét các đoạn mã sau:Thuộc tính C# luôn có trường sao lưu "đằng sau cảnh"?

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

Chương trình này sẽ sản xuất đầu ra với các phương pháp của Test, trong đó sẽ có get_Nameset_Name - bộ thu thập và setters mà tôi đã nói đến. Trong sự hiểu biết của tôi sau đó, nếu getters và setter được tạo ra "đằng sau hậu trường" thì sẽ có một trường sao lưu được tạo ra cũng từ đó/mà getters và setter có được/đặt giá trị. Vì vậy, từ ví dụ trước, tôi có thể dùng phản ánh để kiểm tra các lĩnh vực cho các lớp học thử nghiệm, như vậy:

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

Các ouput của chương trình này là trống rỗng, tôi giả sử điều này là do lĩnh vực sao lưu được tạo ra có private truy cập, vì vậy chúng tôi không thể nhìn thấy nó. Nhưng kể từ khi tôi không biết làm thế nào để kiểm tra nó, bạn có thể vui lòng cho tôi biết nếu một lĩnh vực sao lưu luôn luôn được tạo ra (ngay cả khi chúng tôi có một tài sản đơn giản chỉ với get; và)?

+0

Theo như tôi biết họ làm. – Alex

+5

Chỉ để bạn có thể tìm tài liệu tham khảo khác dễ dàng hơn: chúng thường được gọi là trường * sao lưu *, không phải * trường sao lưu *. –

+0

Hài hước rằng một tính năng được thêm vào trong các phiên bản sau của C# đã làm lu mờ sử dụng chính của họ. – IllidanS4

Trả lời

13

Nếu bạn có nghĩa là tính chất đơn giản như:

{get;set;} 

hay:

{get;} 

sau đó có, có là một lĩnh vực; thêm BindingFlags.NonPublic | BindingFlags.Instance-GetFields() cuộc gọi của bạn và bạn sẽ thấy nó:

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

Nó thường có tên unpronouncable liên quan đến <> - bạn là <Name>k__BackingField trên máy tính của tôi - nhưng: Tên này là một tính năng biên dịch (mặc dù rất nhiều serialization vv thư viện sử dụng nó, vì vậy nó không có khả năng thay đổi).

Nhưng: không, thuộc tính không tự mình luôn liên quan đến các trường; ví dụ:

public int Value => 42; // no field 

hoặc

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

Nhưng kể từ khi tôi không biết làm thế nào để kiểm tra xem nó, bạn có thể xin vui lòng cho tôi biết nếu một lĩnh vực sao lưu luôn được tạo ra (thậm chí nếu chúng ta có một tài sản đơn giản với chỉ nhận được; và thiết lập;?

một tự động thực hiện tài sản, ví dụ như

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

thực sự sẽ luôn có trường hậu thuẫn do trình biên dịch tạo ra. Nhưng nếu bạn cung cấp thực hiện của riêng bạn của getter/setter, sau đó trình biên dịch sẽ không tạo ra một lĩnh vực:

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

Cả những sẽ gây ra một lĩnh vực được tạo ra.

Các vấn đề liên quan