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。无论哪种情况,都不是我的代码。
您实际上没有覆盖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
更派生的对象,您将看不到自己的代码运行。
更新:这仍然留下一些悬而未决的问题:
- 为什么编译器绑定到
MyControl.TabStop
如果变量的静态类型是ClassA
?它不应该绑定到Control.TabStop
吗? - 为什么编译器让你写
Public Overrides Property TabStop As Boolean
如果Control.TabStop
不是虚拟的?
我们知道在Control
和MyControl
之间的层次结构中必须有一些具有虚拟TabStop
属性的类(否则MyControl.TabStop
上的Overrides
将是编译器错误)。我们还知道ClassA.TabStop
最终与MyControl.TabStop
结合。假设在Control
和ClassA
之间的层次结构中没有其他类,那么只有一个逻辑解释:类ClassA
定义了一个虚拟的TabStop
属性Shadows
Control.TabStop
.