16

这听起来可能很幼稚,但是...

class Widget
{
    public int Foo { get; set; }
}

这很酷,并且为使用支持字段节省了一些样板,但在这一点上,它不等同于简单地:

class Widget
{
    public int Foo;
}

似乎它只不过是一个公共领域,尽管我认为它在引擎盖下看起来不同。但是,从设计的角度来看,如果属性不帮助封装,那么使用属性有什么好处呢?

4

6 回答 6

24

因为它使您有可能在以后添加封装逻辑而不更改类的元数据。

使用属性被认为是最佳实践 - 自动实现的属性旨在消除编写属性的繁琐,以鼓励开发人员遵守此最佳实践

于 2011-02-22T03:42:39.493 回答
10

除了到目前为止发布的其他好的答案:

  • 快速创建 private-setter-public-getter 属性很容易,这可以说是比公共只读字段更好的做法来制作不可变数据类型。
于 2011-02-22T03:55:15.317 回答
2
  1. 属性允许您将封装添加到您的类
  2. 如果您选择,属性允许您的访问是多态的(如果属性是虚拟的,继承者可以修改访问)。
  3. 当您处理简单的获取/设置操作时,自动属性很好。如果您在 get / set 中执行更复杂的操作,则无法使用自动属性。

此外,反射在属性上的工作方式与在变量上的工作方式没有什么不同,但您正在使用 MemberInfo(FieldInfo、PropertyInfo 或 MethodInfo,无论您选择哪种方式)。

于 2011-02-22T05:12:50.643 回答
0
  1. 无论出于何种原因,任何程序员都可能需要遵循某种标准
  2. 反射对属性的作用与对变量的作用不同
  3. 您不能对变量进行数据绑定
  4. 如果您决定将其更改为属性,则必须重建所有使用该变量的代码
于 2011-02-22T03:47:08.377 回答
0

来自msdn

属性结合了字段和方法的各个方面。对于对象的用户来说,属性似乎是一个字段,访问该属性需要相同的语法。

你可以这样做:

public class Date
{
private int month = 7;  // Backing store

public int Month
{
    get
    {
        return month;
    }
    set
    {
        if ((value > 0) && (value < 13))
        {
            month = value;
        }
    }
}
}

简而言之,属性更加通用。

于 2011-02-22T03:55:50.107 回答
-1
  • 如果我们的 getter 和/或 setter 没有任何自定义逻辑,我们将使用自动属性。

  • 自动属性还“自动”为我们定义“支持字段”。

这就是我们实现 Auto-property 时“幕后”发生的事情:

你的班:

public class YourClass {
    public int Foo { get; set; }
}

IL代码:

.class private auto ansi '<Module>'
{
} // end of class <Module>

.class public auto ansi beforefieldinit YourClass
    extends [System.Private.CoreLib]System.Object
{
    // Fields
    .field private int32 '<Foo>k__BackingField'  //this is the backing field for your property
    .custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
        01 00 00 00
    )

    // Methods
    .method public hidebysig specialname 
        instance int32 get_Foo () cil managed //this is the GETTER of your property
    {
        .custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
            01 00 00 00
        )
        // Method begins at RVA 0x2050
        // Code size 7 (0x7)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: ldfld int32 YourClass::'<Foo>k__BackingField'
        IL_0006: ret
    } // end of method YourClass::get_Foo

    .method public hidebysig specialname 
        instance void set_Foo (
            int32 'value'
        ) cil managed //this is the SETTER of your property
    {
        .custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
            01 00 00 00
        )
        // Method begins at RVA 0x2058
        // Code size 8 (0x8)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: ldarg.1
        IL_0002: stfld int32 YourClass::'<Foo>k__BackingField'
        IL_0007: ret
    } // end of method YourClass::set_Foo

    .method public hidebysig specialname rtspecialname 
        instance void .ctor () cil managed 
    {
        // Method begins at RVA 0x2061
        // Code size 7 (0x7)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: call instance void [System.Private.CoreLib]System.Object::.ctor()
        IL_0006: ret
    } // end of method YourClass::.ctor

    // Properties
    .property instance int32 Foo()
    {
        .get instance int32 YourClass::get_Foo()
        .set instance void YourClass::set_Foo(int32)
    }

} // end of class YourClass


你也可以在这里查看。

于 2021-05-13T08:19:46.030 回答