关于.net:C#3.0自动属性 – 有用与否?

C# 3.0 auto-properties — useful or not?

注意:这是我开始C时发布的。有了2014年的知识,我真的可以说,汽车属性是C语言所发生过的最好的事情之一。

我习惯于使用私有和公共字段在C中创建我的属性:

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

现在,有了.NET 3.0,我们得到了自动属性:

1
public string Title { get; set; }

我知道这更像是一个哲学/主观问题,但是除了为每个字段保存五行代码之外,是否有任何理由使用这些自动属性?我个人的不满是,这些财产对我隐瞒了一些东西,而我不是黑色魔法的狂热爱好者。

实际上,隐藏的私有字段甚至不会显示在调试器中,这是可以的,因为get/set函数什么也不做。但是当我想要实际实现一些getter/setter逻辑时,无论如何我都必须使用私有/公共对。

我看到了这样的好处:我保存了大量代码(一行对六行),而以后又不丧失更改getter/setter逻辑的能力,但是我同样可以这样做,只需声明一个公共字段"public string title",而不需要get;set;块,这样就可以节省更多的代码。

那么,我在这里错过了什么?为什么会有人真正想要使用自动属性?


我们在堆栈溢出中一直使用它们。

您也可能对属性与公共变量的讨论感兴趣。imho这真的是一种反应,为此目的,它是伟大的。


是的,它只保存代码。当你有很多书的时候,阅读起来容易多了。它们写起来更快,维护起来也更容易。保存代码始终是一个好目标。

您可以设置不同的作用域:

1
public string PropertyName { get; private set; }

以便只能在类内更改属性。这并不是一成不变的,因为您仍然可以通过反射访问私有setter。

从C_6开始,您还可以创建真正的readonly属性,即在构造函数之外不能更改的不可变属性:

1
2
3
public string PropertyName { get; }

public MyClass() { this.PropertyName ="whatever"; }

在编译时将成为:

1
2
3
4
readonly string pName;
public string PropertyName { get { return this.pName; } }

public MyClass() { this.pName ="whatever"; }

在具有大量成员的不可变类中,这可以节省大量多余的代码。


使用字段而不是属性的三大缺点是:

  • 不能将数据绑定到字段,而可以将数据绑定到属性
  • 如果开始使用字段,以后就不能(轻松)将其更改为属性
  • 有些属性可以添加到不能添加到字段的属性中

  • 我个人喜欢汽车用品。保存代码行有什么问题?如果您想在getter或setter中做一些事情,那么稍后将它们转换为普通属性是没有问题的。

    正如您所说,您可以使用字段,如果您想稍后向它们添加逻辑,您可以将它们转换为属性。但这可能会给反射的任何使用带来问题(可能在其他地方?).

    此外,属性还允许您为getter和setter设置不同的访问级别,这是您不能对字段执行的操作。

    我想它和var关键字是一样的。个人喜好问题。


    来自C++的创建者Bjarne Stroustrup:

    I particularly dislike classes with a lot of get and set functions. That is often an indication that it shouldn't have been a class in the first place. It's just a data structure. And if it really is a data structure, make it a data structure.

    你知道吗?他是对的。在get和set中简单地包装私有字段而实际上不在get/set中做任何事情的频率有多高,这仅仅是因为它是"面向对象"的事情。这是微软解决这个问题的方法;它们基本上是可以绑定到的公共字段。


    一件似乎没人提到的事情是,不幸的是,自动属性对于不可变的对象(通常是不可变的结构)没有什么用处。因为你真的应该这样做:

    1
    2
    3
    4
    5
    private readonly string title;
    public string Title
    {
        get { return this.title; }
    }

    (其中字段通过传递的参数在构造函数中初始化,然后是只读的。)

    因此,与简单的get/private set自属性相比,这具有优势。


    我总是创建属性而不是公共字段,因为您可以在接口定义中使用属性,而不能在接口定义中使用公共字段。


    自动属性和C中的其他属性一样具有黑色魔力。一旦你从编译到IL的角度来考虑它,而不是先将它扩展到一个普通的C属性,它就不再像其他语言结构那样具有黑色魔力了。


    我一直使用自动属性。在C 3之前,我不能为所有的输入而烦恼,而是使用公共变量。

    我唯一想做的就是能够做到:

    1
    public string Name ="DefaultName";

    必须将默认值转换为具有属性的构造函数。冗长乏味的:


    我认为任何直观的、减少代码行的构造都是一个很大的优点。

    这些类型的特性使Ruby这样的语言非常强大(它和动态特性,也有助于减少多余的代码)。

    Ruby一直以来都是这样的:

    1
    2
    3
    attr_accessor :my_property
    attr_reader :my_getter
    attr_writer :my_setter

    它很简单,很短,如果您想在属性体的某个位置创建一个真正的实现,它不会破坏类型的外部接口。

    就这么简单。


    我对他们唯一的问题是他们走得不够远。同一版本的编译器添加了自动属性,添加了部分方法。他们为什么不把这两个放在一起,我无法理解。一个简单的"partial onchanged"会让这些东西真正有用。


    在我看来,你应该总是使用自动属性而不是公共字段。也就是说,这是一个折衷方案:

    从使用属性命名约定的内部字段开始。当你第一次

    • 需要从装配外部进入现场,或
    • 需要将逻辑附加到getter/setter

    这样做:

  • 重命名字段
  • 使它成为私人的
  • 添加公共属性
  • 您的客户机代码不需要更改。

    不过,总有一天,您的系统会增长,您会将其分解为单独的程序集和多个解决方案。当这种情况发生时,任何暴露的字段都会再次困扰您,因为正如Jeff提到的,将公共字段更改为公共属性是一个破坏性的API更改。


    这里需要注意的一点是,据我所知,这只是C 3.0端的语法糖,这意味着编译器生成的IL是相同的。我同意避免使用黑魔法,但同样的,用更少的线来画同样的东西通常是一件好事。


    我使用coderush,它比自动属性快。

    这样做:

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

    总共需要八次击键。


    对于代码片段,相同名称的自动属性总共是七次击键;)


    @我不明白……你不能用自动属性来做这个吗?:

    1
    public string Title { get; }

    1
    public string Title { get; private set; }

    这就是你所指的吗?


    我对汽车属性最大的不满是它们的设计是为了节省时间,但我经常发现我必须在以后将它们扩展到全面的属性。

    VS2008缺少的是一个分解的自动属性重构。

    事实上,我们有一个封装字段重构,这使得我的工作方式更快地只使用公共字段。