2008-11-26 8 views
11

Ein seltsames Problem mit einem C# -Code - die Getter-Methode für eine Eigenschaft wird als virtuell angezeigt, wenn sie nicht explizit markiert ist.Warum ist diese Eigenschaft Getter virtuell?

Das Problem zeigt mit der DBKEY Eigenschaft auf dieser Klasse (Code vollständig):

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

Wenn ich Reflektion verwenden, um die DBKEY Eigenschaft zu untersuchen, erhalte ich das folgende (unerwartete) Ergebnis:

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

Warum wird virtualGetter auf True gesetzt? Ich erwartete falsch, angesichts der Tatsache, dass die Eigenschaft weder Zusammenfassung noch virtuelle ist.

Der Vollständigkeit halber - und für die Fern Möglichkeit, sie relevant sind, hier sind die Erklärungen für BusinessEntityKey, IProcessingContextKey und IBusinessEntityKey:

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

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

public interface IBusinessEntityKey 
{ 
    Type GetEntityType(); 
} 

Vielen Dank im Voraus für Ihre Hilfe.

Erläuterung - warum ist das wichtig für mich?

Wir verwenden NHibernate und verfolgten einige Probleme mit Lazy Loading zu Eigenschaften, die nur halb überschreibbar waren - virtueller Getter, aber private Setter. Nachdem diese Festsetzung, haben wir einen Unit-Test alle andere Orte zu fangen, wo dies auftreten könnte:

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

Diese Einheit Test auf der DBKEY Eigenschaft oben erwähnt versagt, und es verstand nicht, warum.

+0

Side Frage, warum ist das ein Problem? – user7116

Antwort

21

Es ist virtuell, weil es eine Schnittstellenmethode implementiert. Schnittstellenimplementierungsmethoden sind immer virtuell, was die CLR betrifft.

6

Der DbKey-Eigenschaft Getter ist in der IL virtuell, da es in einer Schnittstelle ist. Der Setter ist nicht virtuell, da er nicht Teil der Schnittstelle ist, sondern Teil der konkreten Klasse.

ECMA-335: Common Language Infrastructure Abschnitt 8.9.4 stellt fest, dass:

Schnittstellen statisch oder virtuelle Methoden haben kann, aber muss nicht Instanzmethoden haben.

Daher wird der von Ihrer Schnittstelle definierte Getter bei Implementierung in einer abgeleiteten Klasse als virtuell markiert.

5

Link zu der Dokumentation, die erklärt, dass Eigenschaften, die Schnittstellen implementieren, immer als virtuell markiert sind. Um zu sehen, ob es wirklich virtuell ist (da es eine Schnittstelle implementiert), müssen Sie auch überprüfen, ob es IsFinal ist.

Verwandte Themen