C#如何进行动态绑定?

C#如何进行动态绑定?,c#,.net-4.0,C#,.net 4.0,我有一个关于c语言的动态绑定行为的问题 考虑以下对象层次结构: 反对 System.Windows.Forms.Control 甲级 B类 我的班级 可能有额外的类,但这些是我们应该考虑的。对象类和控件类是.NET Framework类。ClassA和ClassB是第三方库类,MyClass是。。。嗯,我的班级。 我已经在MyClass中重写了“Control”的TabStop属性。该属性可能在层次结构中的其他位置被覆盖,但我认为这并不重要。 (MyClass位于另一个程序集中,它是一个vb.n

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

考虑以下对象层次结构:

反对

System.Windows.Forms.Control

甲级

B类

我的班级

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

P>最后,请考虑下面的代码。请注意,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实现,或者可能继承自控件。无论哪种情况,它都不是我的代码


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

您实际上没有重写
TabStop
属性,因为

您所做的是通过创建另一个同名属性来“隐藏”它。因此,当您尝试在此处设置
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绑定解析名称,因为它不是虚拟的。因此,如果不将对象强制转换为比
控件
更派生的对象,则不会看到自己的代码运行

更新:这仍然留下一些悬而未决的问题:

  • 如果变量的静态类型是
    ClassA
    ,为什么编译器绑定到
    MyControl.TabStop
    ?它不应该仍然绑定到
    控件.TabStop
  • 如果
    Control.TabStop
    不是虚拟的,为什么编译器允许您将
    Public Overrides属性TabStop编写为布尔值

  • 我们知道在
    Control
    MyControl
    之间的层次结构中必须有一些类,它们具有虚拟的
    TabStop
    属性(否则
    会覆盖
    MyControl上的
    。TabStop
    将是一个编译器错误)。我们还知道
    ClassA.TabStop
    最终绑定到
    MyControl.TabStop
    。假设在
    Control
    ClassA
    之间的层次结构中没有其他类,那么只有一个逻辑解释:class
    ClassA
    定义了一个虚拟的
    TabStop
    属性,该属性将
    阴影
    控件。TabStop
    您实际上没有覆盖
    TabStop
    属性,因为

    您所做的是通过创建另一个同名属性来“隐藏”它。因此,当您尝试在此处设置
    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绑定解析名称,因为它不是虚拟的。因此,如果不将对象强制转换为比
    控件
    更派生的对象,则不会看到自己的代码运行

    更新:这仍然留下一些悬而未决的问题:

  • 如果变量的静态类型是
    ClassA
    ,为什么编译器绑定到
    MyControl.TabStop
    ?它不应该仍然绑定到
    控件.TabStop
  • 如果
    Control.TabStop
    不是虚拟的,为什么编译器允许您将
    Public Overrides属性TabStop编写为布尔值

  • 我们知道在
    Control
    MyControl
    之间的层次结构中必须有一些类,它们具有虚拟的
    TabStop
    属性(否则
    会覆盖
    MyControl上的
    。TabStop
    将是一个编译器错误)。我们还知道
    ClassA.TabStop
    最终绑定到
    MyControl.TabStop
    。假设在
    Control
    ClassA
    之间的层次结构中没有其他类,那么只有一个逻辑解释:class
    ClassA
    定义了一个虚拟
    TabStop
    属性,该属性将
    阴影
    控件。TabStop

    我要补充一点,这种混淆是“正常的”对于有Java经验的人来说:默认情况下,所有非静态方法都是虚拟的(除非用private或final标记它们)。谢谢你。但它没有解释第二部分。如果我将赋值设置为“((ClassA)c).TabStop=false”,则MyClass中的代码将运行。为什么?@e-mre:这是一个很好的问题。可能
    ClassA
    使用新的虚拟属性对属性
    TabStop
    进行阴影处理,然后覆盖该属性
    MyClass
    ?如果不查看层次结构中所有类的定义,则不能这么说。@xanatos。。。我认为Java方法更有意义。网络行为不符合我头脑中多态性的概念。类的任何用户都希望该类