C# 3.0 自动属性——有用与否? [关闭]

Posted

技术标签:

【中文标题】C# 3.0 自动属性——有用与否? [关闭]【英文标题】:C# 3.0 auto-properties — useful or not? [closed] 【发布时间】:2010-09-05 18:37:38 【问题描述】:

注意:这是在我开始使用 C# 时发布的。凭借 2014 年的知识,我可以真正地说,自动属性是 C# 语言发生过的最好的事情之一。

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

private string title;
public string Title

    get  return title;  
    set  title = value;  

现在,使用.NET 3.0,我们获得了自动属性:

public string Title  get; set; 

我知道这更像是一个哲学/主观问题,但是除了为每个字段保存五行代码之外,还有什么理由使用这些自动属性?我个人的抱怨是这些属性对我隐藏了一些东西,我不是黑魔法的忠实粉丝。

事实上,隐藏的私有字段甚至没有出现在调试器中,考虑到 get/set 函数什么都不做,这是可以的。但是当我想真正实现一些 getter/setter 逻辑时,无论如何我都必须使用 private/public 对。

我看到了节省大量代码(一行代码对六行代码)的好处,而不会失去以后更改 getter/setter 逻辑的能力,但是我已经可以通过简单地声明一个公共字段“公共字符串”来做到这一点标题”而不需要 get;放; 块,从而节省更多代码。

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

【问题讨论】:

“我个人的抱怨是这些属性对我隐藏了一些东西,我不是黑魔法的忠实粉丝。”嗯?您知道编译器一直对您隐藏大量内容,对吗?除非您正在编写程序集(或者更准确地说,代码的实际 1 和 0),否则您编写的所有内容都是对您隐藏的东西。 【参考方案1】:

我们一直在 Stack Overflow 中使用它们。

您可能还对Properties vs. Public Variables 的讨论感兴趣。恕我直言,这确实是对此的反应,为此,它很棒。

【讨论】:

【参考方案2】:

是的,它确实只是保存代码。当您拥有大量它们时,阅读起来会更容易。它们编写起来更快,更容易维护。保存代码始终是一个好目标。

您可以设置不同的范围:

public string PropertyName  get; private set; 

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

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

public string PropertyName  get; 

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

在编译时会变成:

readonly string pName;
public string PropertyName  get  return this.pName;  

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

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

【讨论】:

“所以你不会失去任何功能。”你如何调试它们? @wal - 有什么要调试的?从这个角度来看,您基本上是在处理成员变量。 @wal - 您可以在它们上放置断点,就像您可以访问成员变量一样,您只是无法进入它们。但你为什么想要?自动属性实际上所做的既微不足道又是自动生成的,如果您有错误,那是极不可能出现的地方。 我们可能需要把它带到 Keith 外面。 :) 但是,好吧,假设您有很多对 myObj.Title 的 setter 调用...您想查看值从“text”变为 null 的位置,即条件断点。你是怎么做到的?你甚至不能在 setter 上设置断点【参考方案3】:

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

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

【讨论】:

“如果你开始使用一个字段,你以后不能(轻松地)将它们更改为一个属性”,抱歉,为什么? @Homam 主要是,任何在您的字段上使用反射的消费者代码都会中断,因为它们必须从使用 FieldInfo 切换到 PropertyInfo。 @Homam 此外,将字段更改为属性会破坏二进制兼容性,要求该字段的所有使用者重新编译。 抛开重新编译和反射问题不谈,使用 Visual Studio 封装字段非常容易:Ctrl-R+E 将允许您使用适当的 getter/setter 将字段转换为属性。 (或右键单击字段,重构,封装字段)。 @Hommam 字段是左值(它们是变量),而属性不是。当它是一个字段时可能已经编译的东西在它是一个属性时可能不会编译。【参考方案4】:

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

我特别不喜欢有很多 get 和 set 函数的类。这通常表明它最初不应该是一个类。它只是一个数据结构。如果它真的是一个数据结构,那就让它成为一个数据结构。

你知道吗?他是对的。您多久只是将私有字段包装在 get 和 set 中,而实际上没有在 get/set 中做任何事情,仅仅是因为它是“面向对象”的事情。这是微软对问题的解决方案;它们基本上是您可以绑定到的公共字段。

【讨论】:

我真的觉得这个应该有更多的点。太多的人将 auto 属性视为编写可怕封装(或根本不封装)类的绿灯,这​​些类只不过是一个美化的公共领域。当然,这更多是关于人们如何使用该工具而不是工具本身的问题,但我认为在讨论一般属性时提及这一点很重要。【参考方案5】:

我个人喜欢自动属性。保存代码行有什么问题?如果你想在 getter 或 setter 中做一些事情,以后将它们转换为普通属性是没有问题的。

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

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

我猜它与 var 关键字相同。个人喜好问题。

【讨论】:

【参考方案6】:

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

private readonly string title;
public string Title

    get  return this.title; 

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

所以这比简单的get/private set autoproperty 更有优势。

【讨论】:

如果你有一个结构改变了它的任何属性,就会产生一个新的结构。如果你想要一个内部不可变的引用类型,这只会是一个问题 - 我看不出你需要一个的原因。 @Keith:你的第一句话似乎实际上不正确。 public string Title get; private set; 不会产生完全相同的结果吗?当然,您可以从课堂内部更改它,但是如果这样做,您还有其他问题...:p @Svish - 根据这个论点,C# 中的 readonly 关键字不应该被使用,因为它的使用意味着我们隐藏了这些“不同的问题” 我的意思是,从外部 API 的角度来看,它不会有太大的不同。因此,如果需要,可以使用自动属性。最好的事情当然是如果你能做类似public string Title get; private readonly set; 【参考方案7】:

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

【讨论】:

【参考方案8】:

自动属性与 C# 中的其他任何东西一样是一种黑魔法。一旦您从编译到 IL 的角度考虑它,而不是首先将其扩展为普通的 C# 属性,它就比许多其他语言结构少了很多黑魔法。

【讨论】:

【参考方案9】:

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

我唯一想念的是能够做到这一点:

public string Name = "DefaultName";

您必须将默认值转移到具有属性的构造函数中。乏味:-(

【讨论】:

使用 C# 6 中的自动属性初始化器,您很快就能做到这一点:public string Name get; set; = "DefaultName";blogs.msdn.com/b/csharpfaq/archive/2014/11/20/…【参考方案10】:

我认为任何直观且减少代码行数的结构都是一大优势。

正是这些特性让 Ruby 等语言如此强大(动态特性也有助于减少多余的代码)。

Ruby 一直以来都是这样的:

attr_accessor :my_property
attr_reader :my_getter
attr_writer :my_setter

【讨论】:

【参考方案11】:

我对他们的唯一问题是他们走得不够远。同一版本的编译器添加了自动属性,添加了部分方法。为什么他们没有把两者放在一起是超出我的。一个简单的“partial OnChanged”会让这些东西非常有用。

【讨论】:

您可以将多个部分方法放在另一个方法中。为他们创建某种自动模式会令人困惑。【参考方案12】:

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

就这么简单。

【讨论】:

【参考方案13】:

这里要注意一点,据我了解,这只是 C# 3.0 端的语法糖,意思是编译器生成的IL 是一样的。我同意避免使用黑魔法,但同样的,同一件事的行数越少通常是一件好事。

【讨论】:

【参考方案14】:

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

使用您将用于属性的命名约定从internal 字段开始。当你第一次

需要从其程序集外部访问该字段,或 需要将逻辑附加到 getter/setter

这样做:

    重命名字段 将其设为私有 添加公共属性

您的客户端代码无需更改。

不过,总有一天,您的系统会发展壮大,您会将其分解为单独的程序集和多个解决方案。发生这种情况时,任何暴露的字段都会回来困扰您,因为正如 Jeff 所说,changing a public field to a public property is a breaking API change。

【讨论】:

【参考方案15】:

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

为此:

 private string title;
public string Title

    get  return title;  
    set  title = value;  

总共需要 8 次击键。

【讨论】:

如果我按住 CTRL 和 V,我可以粘贴很多很多东西,/真的很快/,但这并不能让它变得“更好”。这如何回答最初的问题?【参考方案16】:

如果使用代码 sn-ps,同名的自动属性将总共是 7 次击键;)

【讨论】:

【参考方案17】:

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

public string Title  get; 

public string Title  get; private set; 

你指的是这个吗?

【讨论】:

您可以(后者;前者不会编译),但是该字段在您的对象内部不是不可变的。 请注意,只有结构在标记为只读时是不可变的,类是不可分配的。【参考方案18】:

我对自动属性最大的抱怨是它们旨在节省时间,但我经常发现我必须稍后将它们扩展为完整的属性。

VS2008 缺少的是 Explode Auto-Property 重构。

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

【讨论】:

以上是关于C# 3.0 自动属性——有用与否? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

C# 3.0新语言特性和改进

自动扩展 C# 3 语法糖

C# 知识体系构建| | C# 3.0 上

用pip命令安装python第三方库,无论安装结果成功与否,命令提示符窗口都会自动关闭?

Python Flask自动生成的SwaggerOpenAPI 3.0[已关闭]。

C#自动弹出窗口并定时自动关闭