2008-11-26 11 views
11

Có vấn đề lạ với một số mã C# - phương pháp Getter cho thuộc tính được hiển thị dưới dạng ảo khi không được đánh dấu rõ ràng.Tại sao tài sản này là Getter ảo?

Vấn đề triển lãm với tài sản DbKey trên lớp này (mã đầy đủ):

public class ProcessingContextKey : BusinessEntityKey, IProcessingContextKey 
{ 
    public ProcessingContextKey() 
    { 
     // Nothing 
    } 

    public ProcessingContextKey(int dbKey) 
    { 
     this.mDbKey = dbKey; 
    } 

    public int DbKey 
    { 
     get { return this.mDbKey; } 
     set { this.mDbKey = value; } 
    } 
    private int mDbKey; 

    public override Type GetEntityType() 
    { 
     return typeof(IProcessingContextEntity); 
    } 
} 

Khi tôi sử dụng phản xạ để kiểm tra tài sản DbKey, tôi nhận được như sau (bất ngờ) Kết quả:

Type t = typeof(ProcessingContextKey); 
PropertyInfo p = t.GetProperty("DbKey"); 
bool virtualGetter = p.GetGetMethod(true).IsVirtual; // True! 
bool virtualSetter = p.GetSetMethod(true).IsVirtual; // False 

Tại sao virtualGetter được đặt thành True? Tôi dự kiến ​​sai, vì thuộc tính đó không phải là trừu tượng cũng không phải virtual.

Đối với đầy đủ - và cho possibilty từ xa họ có liên quan, đây là tờ khai cho BusinessEntityKey, IProcessingContextKey, và IBusinessEntityKey:

public abstract class BusinessEntityKey : IBusinessEntityKey 
{ 
    public abstract Type GetEntityType(); 
} 

public interface IProcessingContextKey : IBusinessEntityKey 
{ 
    int DbKey { get; } 
} 

public interface IBusinessEntityKey 
{ 
    Type GetEntityType(); 
} 

Cảm ơn trước sự giúp đỡ của bạn.

Làm rõ - tại sao điều này lại quan trọng với tôi?

Chúng tôi đang sử dụng NHibernate và truy tìm một số vấn đề với tải chậm đối với các thuộc tính chỉ có một nửa có thể ghi đè - trình gỡ rối ảo nhưng thiết lập riêng tư. Sau khi sửa chữa chúng, chúng tôi đã thêm một thử nghiệm đơn vị để đón bất kỳ nơi khác, nơi này có thể xảy ra:

public void RequirePropertiesToBeCompletelyVirtualOrNot() 
{ 
    var properties 
     = typeof(FsisBusinessEntity).Assembly 
      .GetExportedTypes() 
      .Where(type => type.IsClass) 
      .SelectMany(
       type => 
        type.GetProperties(
         BindingFlags.Instance 
         | BindingFlags.Public 
         | BindingFlags.NonPublic)) 
      .Where(property => property.CanRead 
       && property.CanWrite) 
      .Where(property => 
       property.GetGetMethod(true).IsVirtual 
        != property.GetSetMethod(true).IsVirtual); 

    Assert.That(
     properties.Count(), 
     Is.EqualTo(0), 
     properties.Aggregate(
      "Found : ", 
      (m, p) => m + string.Format("{0}.{1}; ", 
        p.DeclaringType.Name, 
        p.Name))); 
} 

Đơn vị này thử nghiệm đã thất bại về tài sản DbKey đề cập ở trên, và tôi không hiểu tại sao.

+0

Câu hỏi phụ, tại sao đây lại là vấn đề? – user7116

Trả lời

21

Đó là ảo vì nó thực hiện một phương thức giao diện. Các phương thức triển khai giao diện luôn luôn ảo theo như CLR có liên quan.

6

Bộ khởi động thuộc tính DbKey là ảo trong IL vì nó nằm trong giao diện. Setter không phải là ảo vì nó không phải là một phần của giao diện mà là một phần của lớp bê tông.

ECMA-335: Common Language Infrastructure Phần 8.9.4 ghi chú rằng:

Giao diện có thể có phương pháp tĩnh hoặc ảo, nhưng không có phương pháp dụ.

Do đó trình thu thập được xác định bởi giao diện của bạn sẽ được đánh dấu ảo khi được triển khai trong lớp dẫn xuất.

5

Link vào tài liệu giải thích rằng các thuộc tính triển khai giao diện luôn được đánh dấu là ảo. Để xem nếu nó thực sự là ảo (vì nó thực hiện một giao diện), bạn cũng sẽ cần phải kiểm tra xem nó là IsFinal.

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