2008-11-26 113 views
11

對於某些C#代碼有一個奇怪的問題 - 屬性的Getter方法在未明確標記時顯示爲虛擬。爲什麼這個屬性Getter虛擬?

問題表現出與DBKEY財產在這個類(在全碼):

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

當我使用反射來檢查DBKEY財產,我得到以下(意外)結果:

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

爲什麼virtualGetter設置爲True?我預計假的,因爲該屬性既不是抽象也不是虛擬

爲了完整性 - 和遠程possibilty它們是相關的,這裏有BusinessEntityKey,IProcessingContextKey和IBusinessEntityKey聲明:

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

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

public interface IBusinessEntityKey 
{ 
    Type GetEntityType(); 
} 

在此先感謝您的幫助。

澄清 - 這事爲什麼給我?

我們正在使用NHibernate和追蹤與延遲加載一些問題是隻有一半的重寫特性 - 虛擬的getter但私人二傳手。解決這些後,我們增加了一個單元測試來捕捉任何其他地方可能出現這種情況:

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

這個單元測試不及格就上述DBKEY財產,我不明白爲什麼。

+0

旁邊的問題,爲什麼這是一個問題? – user7116 2008-11-26 20:48:43

回答

21

它是虛擬的,因爲它實現了一種接口方法。就CLR而言,接口實現方法始終是虛擬的。

6

的DBKEY屬性getter是在IL虛擬因爲它是在一個接口。 setter不是虛擬的,因爲它不是界面的一部分,而是具體類的一部分。

ECMA-335: Common Language Infrastructure第8.9.4注意到:

接口可以有靜態的或虛擬的方法,但不得有實例方法。

因此,在派生類中實現時,由接口定義的getter將標記爲虛擬。

5

Link到解釋說,實現接口屬性始終標示虛擬的文檔。要看它是否真的是虛擬的(因爲它實現了一個接口),你還需要檢查它是否是最終的。