代码之家  ›  专栏  ›  技术社区  ›  Bevan

为什么这个属性Getter是虚拟的?

  •  11
  • Bevan  · 技术社区  · 16 年前

    某些C#代码有一个奇怪的问题-属性的Getter方法在没有显式标记时显示为virtual。

    此类上的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);
        }
    }
    

    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?考虑到该属性既不是 摘要 也没有 .

    public abstract class BusinessEntityKey : IBusinessEntityKey
    {
        public abstract Type GetEntityType();
    }
    
    public interface IProcessingContextKey : IBusinessEntityKey 
    {
        int DbKey { get; }
    }
    
    public interface IBusinessEntityKey
    {
        Type GetEntityType();
    }
    

    提前感谢你的帮助。

    澄清

    我们正在使用NHibernate,并跟踪了延迟加载到只有半可重写属性(虚拟getter但私有setter)的一些问题。在解决这些问题之后,我们添加了一个单元测试来捕获可能发生这种情况的任何其他地方:

    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属性上失败了,我不明白为什么。

    3 回复  |  直到 16 年前
        1
  •  21
  •   Toon Krijthe    16 年前

    它是虚拟的,因为它实现了一个接口方法。就CLR而言,接口实现方法始终是虚拟的。

        2
  •  6
  •   user7116    16 年前

    DbKey属性getter在IL中是虚拟的,因为它位于接口中。setter不是虚拟的,因为它不是接口的一部分,而是具体类的一部分。

    ECMA-335: Common Language Infrastructure

    接口可以有静态或虚拟方法,但不能有实例方法。

    因此,当在派生类中实现时,接口定义的getter将被标记为virtual。

        3
  •  5
  •   tvanfosson    16 年前