c#是如何实现动态绑定的

本文关键字:实现 动态绑定 何实现 | 更新日期: 2023-09-27 18:08:09

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

考虑以下对象层次结构:

对象

System.Windows.Forms。控制

ClassA

ClassB

MyClass

中间可能还有其他类,但这些是我们应该考虑的。对象类和控制类是。net框架类。类a和类b是第三方库类,MyClass是……嗯,我的课。
我已经覆盖了"控制"的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。无论哪种情况,都不是我的代码。

谁能解释一下这种行为?

c#是如何实现动态绑定的

您实际上没有覆盖TabStop属性,因为它不是虚拟的。

你所做的是通过创建另一个同名的属性来"隐藏"它。因此,当您尝试在这里设置Control.TabStop时,将执行不同的属性setter:

// 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不是虚拟的?

我们知道在ControlMyControl之间的层次结构中必须有一些具有虚拟TabStop属性的类(否则MyControl.TabStop上的Overrides将是编译器错误)。我们还知道ClassA.TabStop最终与MyControl.TabStop结合。假设在ControlClassA之间的层次结构中没有其他类,那么只有一个逻辑解释:类ClassA定义了一个虚拟的TabStop属性Shadows Control.TabStop .