我正在尝试更多地了解编程,特别是面向对象的编程。
我有一本书解释了如何创建属性,但它们也将它与私有变量结合起来。我不明白为什么他们这样做,以及这样做的好处是什么。
以下是示例代码。
Namespace PropertyExample
Class Person
Private _Name As String
Public Property Name() As String
Get ' (1)
Name = _Name
End Get
Set(ByVal value As String) ' (2)
_Name = value
End Set
End Property
End Class
我是另一个例子,他们这样写,我的意见很清楚。
Class Person
Public Property Name() As String
End Class
答案 0 :(得分:1)
which is alot cleaner is my opinion
后者称为自动实现的属性。编译器提供可以减少锅炉板代码的支持字段。您仍然可以在代码中引用_Name
私人成员。
更好/更清洁取决于。在这种情况下你需要完整版本:
Public ReadOnly Property Age As Integer
Get
If DateOfBirth <> DateTime.MinValue Then
Return (DateTime.Now.Year - DateOfBirth.Year)
Else
Return 0
End If
End Get
End Property
类似的示例是集合类上的只读Count
属性。或者:
Private _name As String = ""
Public Property Name As String
Get
Return _name
End Get
Set(value As String)
If _name.ToLowerInvariant <> value.ToLowerInvariant Then
_name = value
NotifyPropertyChanged()
End If
End Set
End Property
有时候无法使用自动工具版本。作为一本书,我希望它能够覆盖/显示两种方式,至少对于那些拥有旧版本VS的人来说。
自动实施的属性在VS 2010中可用; .NET Framework版本并不重要,因为它是一个编译器功能。
答案 1 :(得分:1)
class
的原因只能在此property
内访问。
仔细观察后,您会看到Name
被称为variable
,_Name
被称为naming convention
。它是variable
,您应该使用它。即使是来自property
之外的任何其他类,也不应该访问property
。
即public
classes
来自不同projects
和Private _Name As String
Public Property Name() As String
Get ' (1)
Name = _Name
End Get
Set(ByVal value As String) ' (2)
_Name = value
End Set
End Property
的{{1}}。
你展示了财产的共同外观:
Private _Name As String
Public ReadOnly Property Name() As String
Get ' (1)
Name = _Name
End Get
End Property
其他包括readonly,writeonly:
Private _Name As String
Public ReadOnly Property Name() As String
Get ' (1)
If Strinf.IsnullOrEmpty(_Name)
_Name = Somemethod()
End if
Return _Name
End Get
End Property
另一个好例子是:
{{1}}
首次使用时会初始化此属性。
答案 2 :(得分:1)
您提到的第一种方法是在.NET 3.5之前可以编写属性的唯一方法。
第二个名为Auto-Implemented Property,引入了C#3.0 / .NET 3.5。
在内部,自动实现的属性也使用私有变量来存储数据。它只是编译器添加的语法糖,以节省开发人员一点时间并使代码更具可读性。
为什么要使用可见的声明变量而不仅仅使用自动实现的属性?
嗯,这取决于你的程序的上下文。如果您只想要一个名称变量的1:1公共映射器,您可以使用自动实现。
但是,如果在设置/获取变量值时需要一些逻辑,则 以使用额外变量方法。
假设您要求应用中的名称不得超过50个字符。您可以在属性的setter中处理此验证:
Set(ByVal value As String)
If value.Length <= 50
_Name = value
Else
'Throw some validation error
End if
End Set
只有定义了变量(此处为_Name)才能执行此操作。使用自动实现的属性不可能做到这一点。
如果您对细节感兴趣:
您的两个代码段都产生(差不多)相同的MSIL:
Person.get_Name:
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld UserQuery+Person._Name
IL_0007: stloc.0 // Name
IL_0008: br.s IL_000A
IL_000A: ldloc.0 // Name
IL_000B: ret
Person.set_Name:
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.1
IL_0003: stfld UserQuery+Person._Name
IL_0008: nop
IL_0009: ret
VS
Person.get_Name:
IL_0000: ldarg.0
IL_0001: ldfld UserQuery+Person._Name
IL_0006: stloc.0
IL_0007: br.s IL_0009
IL_0009: ldloc.0
IL_000A: ret
Person.set_Name:
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld UserQuery+Person._Name
IL_0007: nop
IL_0008: ret
正如您所看到的,两个片段都在变量_Name
(stfld)中读取/写入其字符串值。
(唯一的区别是调试时使用的nop
命令,可以在这里忽略。)