Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
VB.Net中可重写属性上的速记符号不起作用_Vb.net_Class_Oop - Fatal编程技术网

VB.Net中可重写属性上的速记符号不起作用

VB.Net中可重写属性上的速记符号不起作用,vb.net,class,oop,Vb.net,Class,Oop,在我的VB.Net代码中,我知道当我在类中声明一个属性时,我可以使用缩写,例如,公共属性Prop1 As String,.Net自动创建一个私有变量\u Prop1,我可以在类中引用它 我还知道,我可以使用\u Prop1或Prop1在代码中引用该变量 现在,由于我一直认为首选方法是使用私有变量,所以我一直尝试在类中引用\u Prop1进行修改/编写代码。这就是我现在的问题所在 我有以下情况: Public Class MyClass_Base Public Overridable Pro

在我的VB.Net代码中,我知道当我在类中声明一个属性时,我可以使用缩写,例如,
公共属性Prop1 As String
,.Net自动创建一个私有变量
\u Prop1
,我可以在类中引用它

我还知道,我可以使用
\u Prop1
Prop1
在代码中引用该变量

现在,由于我一直认为首选方法是使用私有变量,所以我一直尝试在类中引用
\u Prop1
进行修改/编写代码。这就是我现在的问题所在

我有以下情况:

Public Class MyClass_Base
   Public Overridable Property Prop1 As String = "val1"

   Public Sub Test()
       If _Prop1 = ....
   End Sub
End Class

Public Class MyClass
   Inherits MyClass_Base

   Public Overrides Property Prop1 As String = "val2"
End Class
基本上,我在基类中将属性定义为可重写,现在当我进入
Test()
子例程时,
\u Prop1
的值为
Nothing
。但是
Prop1
具有正确的值
val2

编程大师们,处理这种情况的正确方法是什么? 我是否忽略了自动创建的prive变量
\u Prop1
并与公共
Prop1
一起工作,或者是否有其他东西我应该添加/甚至不使用简写符号,并编写我自己的getter/setter逻辑以确保事情按照我的意愿进行更改


谢谢

我想你已经回答了你自己的问题。您绝对不应该在自己的代码中依赖隐藏的编译器机制。您正在引用一个未声明的变量,并且在框架中无法保证该变量会存在(或者按照您的预期工作,正如您所发现的那样)-使用它是一种黑客行为,因此不要这样做

除非您有很好的理由不这样做,否则类中的代码应该引用公共属性,就像使用该类的代码一样。如果您使用的是自动属性,那么这样做与使用私有变量没有区别。它还有一个好处,就是如果您稍后决定实现显式的getter和setter,那么代码不会中断,新的getter和setter也会被调用

要探究您获得意外结果的原因,请在

  Public Overrides Property Prop1 As String = "val2"
您将得到两个不同的
\u Prop1
变量-
MyClass\u Base.\u Prop1
MyClass.\u Prop1
。然后调用
Test()
时,调用的是基类方法,该方法将引用基类的
\u Prop1
变量,该变量在重写子类中的隐式变量getter和setter后未设置为任何值

为了说明这一点,这类似于:

Public Class MyClass_Base
    Private _Prop1 As String = "val1"

    Public Sub Test()
        Console.WriteLine(_Prop1)
    End Sub
End Class

Public Class MySubClass
    Inherits MyClass_Base
    Private _Prop1 As String = "val2"
End Class

Sub Main()
    Dim class1 As New MyClass_Base
    Dim class2 As New MySubClass
    class1.Test()
    class2.Test()
End Sub
您的输出将在哪里:

 val1
 val1
在上面的例子中,
MyClass\u Base.\u Prop1
总是初始化的,但是在您的例子中,它不是。在任何一种情况下,
Test()
方法都属于基类,因此它总是引用自己的
\u Prop1
,而不是子类中声明的任何同名变量

如果您确实需要引用私有字段,无论出于何种原因,您都必须非常小心如何使用它(以及随之而来的含义)。如果子类打算以相同的方式使用它们自己的私有变量,那么任何这样做的方法本身都需要是可重写的。不是建议您继续使用隐式变量,而是为了证明:

Public Class MyClass_Base
    Public Overridable Property Prop1 As String = "val1"

    Public Overridable Sub Test()
        Console.WriteLine(_Prop1)
    End Sub
End Class

Public Class MySubClass
    Inherits MyClass_Base
    Public Overrides Property Prop1 As String = "val2"
    Public Overrides Sub Test()
        Console.WriteLine(_Prop1)
    End Sub
End Class
这里我们得到了“预期”的结果,因为
MySubClass
覆盖测试以引用它自己的私有字段。最好只使用属性名。

从:

“为属性指定的属性不适用于支持字段。”

这是C#和VB.NET需要对齐的领域之一

C#(正确)不允许您访问自动实现的属性备份字段(没有一些复杂的工作)。我真的不知道你能用VB访问什么

因此,这里的规则是,即使您可以访问自动实现的属性的backing字段,您也不应该直接修改它(也不应该这样做)

如果需要,则应使用已定义的支持字段(带有初始化)和显式
Get
Set