C#如何进行动态绑定?

时间:2011-09-09 07:13:19

标签: c# .net-4.0

我有关于c#语言动态绑定行为的问题。

考虑以下对象层次结构:

  

对象

     
    

System.Windows.Forms.Control

         
      

ClassA

             
        

ClassB

                 
          

MyClass

        
      
    
  

可能会有其他类,但这些是我们应该考虑的。 Object和Control类是.NET Framework类。 ClassA和ClassB是第三方库类,MyClass是......好吧,我的班级 我在MyClass中重写了“Control”的TabStop属性。该属性可能会在层次结构中的其他位置被覆盖,但我认为这并不重要 (MyClass在另一个程序集中,这是一个vb.net项目)

Public Overrides Property TabStop As Boolean
    Get
        Return MyBase.TabStop
    End Get
    Set(value As Boolean)
        MyBase.TabStop = value
    End Set
End Property

最后,请考虑以下代码。请注意,myControlCollection中的某些对象是MyClass类型,其他对象不是。:

        foreach (Control c in myControlCollection)
        {
            if (c is ClassA)
            {
                if (((ClassA)c).Properties.ReadOnly) c.TabStop = false;
            }
        }

现在问题是: 我在MyClass的TabStop属性的setter方法中设置了一个断点。

如果代码按上面给出的那样运行,则不会对集合中的任何对象点击断点。

如果我将行更改为...

  

((ClassA)c).TabStop = false;

... visual studio命中MyClass声明中的断点。

这让我很困惑。当通过“Control”类型的变量调用属性时,为什么不会触发断点。即使变量是Control类型,实际对象也是MyClass类型,所以我认为断点应该被击中。
第二,如果在通过Control类型的变量调用时没有命中,为什么在我将变量转换为ClassA时它会命中。我没有将它转换为MyClass,我将它转换为基类,它可能有自己的TabStop实现,或者可能从Control继承。无论哪种情况,都不是我的代码。

有人可以解释一下这种行为吗?

1 个答案:

答案 0 :(得分:5)

您实际上并未覆盖TabStop属性,因为it is not virtual

您所做的是通过创建具有相同名称的另一个属性来“隐藏”它。因此,当您尝试在此处设置Control.TabStop时,会执行不同的属性设置器:

// The static type of c is Control!
if (((ClassA)c).Properties.ReadOnly) c.TabStop = false;

当你在这里设置时:

// The static type is now ClassA
((ClassA)c).TabStop = false;

当您引用该属性时,编译器使用 static 绑定解析名称,因为它不是虚拟的。因此,如果您不将对象强制转换为比Control更加派生的对象,则不会看到自己的代码运行。

更新:这仍有一些悬而未决的问题:

  1. 如果变量的静态类型为MyControl.TabStop,为什么编译器会绑定到ClassA?它不应该仍然绑定到Control.TabStop
  2. 如果Public Overrides Property TabStop As Boolean不是虚拟的话,为什么编译器会让你写Control.TabStop
  3. 我们知道ControlMyControl之间的层次结构中必须有某些类,并且具有虚拟TabStop属性(否则为OverridesMyControl.TabStop上将是编译器错误)。我们也知道ClassA.TabStop最终会绑定到MyControl.TabStop。假设ControlClassA之间的层次结构中没有其他类,则只有一个逻辑解释:类ClassA定义TabStop的虚拟Shadows属性} Control.TabStop