类属性实现样式

时间:2016-03-29 10:42:32

标签: .net vb.net class properties

我正在尝试更多地了解编程,特别是面向对象的编程。

我有一本书解释了如何创建属性,但它们也将它与私有变量结合起来。我不明白为什么他们这样做,以及这样做的好处是什么。

以下是示例代码。

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

3 个答案:

答案 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来自不同projectsPrivate _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)

  1. 您提到的第一种方法是在.NET 3.5之前可以编写属性的唯一方法。

  2. 第二个名为Auto-Implemented Property,引入了C#3.0 / .NET 3.5。

  3. 在内部,自动实现的属性也使用私有变量来存储数据。它只是编译器添加的语法糖,以节省开发人员一点时间并使代码更具可读性。

    为什么要使用可见的声明变量而不仅仅使用自动实现的属性?

    嗯,这取决于你的程序的上下文。如果您只想要一个名称变量的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命令,可以在这里忽略。)