关于c#:.NET中的Getter和Setter声明

Getter and Setter declaration in .NET

本问题已经有最佳答案,请猛点这里访问。

我想知道getter和setter声明之间的区别是什么,以及是否存在首选方法(以及为什么)。第一个可以由Visual Studio自动生成。其他人呢?谢谢

第一

1
string _myProperty { get; set; }

第二

1
2
3
4
5
6
7
string _myProperty;

public string myProperty
{
    get { return _myProperty; }
    set { _myProperty = value; }
}

第三

1
2
3
4
5
6
7
8
9
10
11
string _myProperty;

public string getMyProperty()
{
  return this._myProperty;
}

public void setMyProperty(string value)
{
  this._myProperty = value;
}


属性用于封装某些数据。您可以使用普通字段:

1
public string MyField

但是这个字段可以被类的所有外部用户访问。人们可以插入非法值或以您不期望的方式更改值。

通过使用属性,可以封装数据的访问方式。C有一个很好的语法,可以将字段转换为属性:

1
string MyProperty { get; set; }

这称为自动实现的属性。当需要时,您可以将您的财产扩展到:

1
2
3
4
5
6
7
string _myProperty;

public string MyProperty
{
    get { return _myProperty; }
    set { _myProperty = value; }
}

现在,您可以添加验证setter中值的代码:

1
2
3
4
5
6
7
set
{
    if (string.IsNullOrWhiteSpace(value))
        throw new ArgumentNullException();

    _myProperty = value;
}

属性还可以为getter和setter使用不同的访问器:

1
public string MyProperty { get; private set; }

这样,您就创建了一个属性,每个人都可以读取它,但只能由类本身修改它。

您还可以为您的getter添加完全自定义的实现:

1
2
3
4
5
6
7
public string MyProperty
{
    get
    {
        return DateTime.Now.Second.ToString();
    }
}

当C编译自动实现的属性时,它会生成中间语言(IL)。在您的IL中,您将看到一个get_MyPropertyset_MyProperty方法。它还创建了一个名为k_BackingField的支持字段(通常这在C中是非法名称,但在IL中是有效的)。这样就不会在生成的类型和您自己的代码之间产生任何冲突)。但是,您应该使用C中的官方属性语法。这在C中创造了更好的体验(例如使用IntelliSense)。

按照惯例,对于需要很长时间的操作,不应该使用属性。


好吧,第一个和第二个都会产生类似于第三个的结果。但是,当您有属性语法时,不要使用第三个。

最后,如果您在getset中没有工作要做,那么使用第一个。

最后,第一个和第二个只是某种形式的句法糖分,但为什么代码比必要的要多。

1
// more code == more bugs

为了好玩,考虑一下:

1
public string A { get; private set; }

现在说得更直接了,不是吗?public修饰语在getset上都是隐含的,但它可以被重写。当然,对于定义属性本身时使用的任何修饰符,这都是相同的规则。


第一

1
string _myProperty { get; set; }

这在.NET世界中被称为自动属性。它只是2的句法糖。

第二

1
2
3
4
5
6
7
string _myProperty;

public string myProperty
{
    get { return _myProperty; }
    set { _myProperty = value; }
}

这是通常的方法,如果您需要在您的属性中进行任何验证或额外的代码,就需要这样做。例如,在WPF中,如果需要触发属性更改事件。如果不这样做,只需使用auto属性,它就相当标准了。

1
2
3
4
5
6
7
8
9
10
11
string _myProperty;

public string getMyProperty()
{
    return this._myProperty;
}

public string setMyProperty(string value)
{
    this._myProperty = value;
}

这里的this关键字是多余的。根本不需要。这些只是与属性相对应的获取和设置的方法,比如Java的做事方式。


这样,您就可以在getset范围内执行一些代码。

1
2
3
4
5
6
private string _myProperty;
public string myProperty
{
    get { return _myProperty; }
    set { _myProperty = value; }
}

您还可以使用自动属性:

1
2
3
4
5
public string myProperty
{
    get;
    set;
}

NET框架将为您管理。它之所以被创造,是因为它是一个很好的实践,而且很容易做到。

您还可以控制这些范围的可见性,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public string myProperty
{
    get;
    private set;
}

public string myProperty2
{
    get;
    protected set;
}

public string myProperty3
{
    get;
}

更新

现在在C中,您可以初始化属性的值。样品:

1
public int Property { get; set; } = 1;

如果也可以定义它并使其成为只读的,而不需要设置。

1
public int Property { get; } = 1;

最后,您可以定义一个箭头函数。

1
public int Property { get; } => GetValue();

只是澄清一下,在第三个示例中,myproperty实际上不是一个属性。这是一个包含get和set方法的字段(正如前面提到的,get和set方法应该指定返回类型)。

在大多数情况下,应避免使用第三种方法。如果要返回的类型是数组,或者get方法做了很多工作,而不仅仅是返回一个值,那么只需要使用它。后者并非真正必要,但为了清晰起见,执行大量工作的属性的get方法具有误导性。


让我们从3开始。那是行不通的。public getMyProperty()没有返回类型。

数字1和2实际上是一样的。2是编译后的数字1。

所以1和2是一样的。有了两个,您可以在模型中进行一些验证或缓存。

除此之外,它们变得相同。


第一个是"短"形式——当你不想对你的getter和setter做一些花哨的事情时,你就使用它。不可能以这种形式执行方法或类似的东西。

第二种和第三种形式几乎相同,尽管第二种形式被压缩成一行。StyleCop不鼓励这种形式,因为它看起来有点奇怪,不符合C'StyleGuides。

如果我希望使用getter/setter来处理一些特殊的事情,比如使用懒惰的结构,我会使用第三种形式。


第一个是默认值,当没有特殊的返回或写入时。第二个和第三个基本相同,其中第三个是第二个扩展版本