2010-06-18 33 views
30

首先,我已阅读了关于此主题的帖子列表,并且我并不认为我已经掌握了属性,因为我已经了解了封装和字段修饰符(私有,公共...等)。属性与字段:需要帮助掌握属性在字段上的用法

我已经学习了C#的一个主要方面,就是使用封装在代码中保护数据的重要性。我'认为'我明白这是因为使用修饰语(私人,公共,内部,受保护)的能力。然而,在了解了属性之后,我不仅在理解属性的使用方面存在困难,而且在理解C#中数据保护的整体重要性/能力(我认为是封装)。

更具体地讲,一切我已阅读,当我在C#中得到了性质是,你应该尝试使用他们在的地方字段时,你可以因为:

1)它们允许你如果直接直接访问字段时无法更改数据类型。

2)他们的保护级别添加到数据访问

然而,从我“想”我是来了解采用现场改性剂做了#2,这在我看来,性质只是生成额外的代码,除非你有理由改变类型(#1) - 因为你(或多或少)创建隐藏的方法来访问字段,而不是直接。

然后就是可以将所有修饰符添加到属性中,这进一步使我对需要属性访问数据的理解变得复杂。

我已经阅读了许多关于“属性”的不同作者的章节,没有一篇真正解释了对属性与字段与封装(以及良好的编程方法)的良好理解。

有人能解释一下:

1)我为什么要使用属性,而不是领域(尤其是当它出现,我只是添加额外的代码

2)上的任何提示在追踪其他人的代码时,认识到使用属性并且不把它们视为简单的方法(除get; set是显而易见的)?

3)任何一般的经验法则,当涉及到什么时候使用什么好的编程方法?

感谢和抱歉的长篇文章 - 我不想问一个已经被问到100x的问题,而没有解释我为什么再次提问。

+1

重复? http://stackoverflow.com/questions/2911945/method-calling-public-private-members-or-methods-best-practice-c-net/ – 2010-06-18 13:24:07

+2

似乎没有人链接到[为什么属性](http:///csharpindepth.com/Articles/Chapter8/PropertiesMatter.aspx)。在过去,我发现这个概述很有帮助。 – R0MANARMY 2010-06-18 14:19:04

回答

8

您不必担心通过属性访问字段所需的额外代码,它将由JIT编译器(通过内联代码)“优化”掉。除非内联过大,否则你需要额外的代码。

以及用于定义简单属性的额外的代码也微乎其微:

public int MyProp { get; set; } // use auto generated field. 

当你需要定制可以送花儿给人后来定义自己的领域。

所以,你剩下了额外的封装/数据保护层,这是一件好事。

我的规则:总是暴露领域通过属性

0

属性是覆盖领域执行封装的首选方法。然而,它们的功能在于你可以公开一个不同类型的属性并编组投射;你可以改变访问修饰符;它们用于WinForms数据绑定;它们允许您嵌入轻量级的每个属性逻辑,例如更改通知;等等。

在查看其他人的代码时,属性对方法具有不同的智能图标。

如果你觉得性只是额外的代码,我将与他们无论如何据理力争,但坚持让您的生活通过自动生成来自外地的财产更容易(右击 - >重构 - >封装字段...)

3

有些情况下使用一个简单的现场不会造成损害,
一个属性可以更容易地后来改变,也就是说,如果你想添加一个事件每当值改变或需要执行一些价值许多场景/范围检查。

另外,如果您有多个项目相互依赖,则必须重新编译所有依赖字段更改为属性的项目。

2

why I would want to use properties instead of fields (especially when it appears I am just adding additional code

您想使用性能在田野监守,当您使用属性,你可以在一个情况下使用的事件和他们在一起,所以当你想要做一些动作时,属性发生变化时,可以将一些处理器到PropertyChanging或PropertyChanged事件。如果是田地,这是不可能的。字段可以是公开的,也可以是私人的,也可以是受保护的,如果是道具,您可以公开只读,但可以私下写入。

any tips on recognizing the use of properties and not seeing them as simply methods (with the exception of the get;set being apparent) when tracing other peoples code?

的方法应该当返回值预期是动态的每次调用中使用,属性时,应使用的返回值是不是大动态的。

Any general rules of thumb when it comes to good programming methods in relation to when to use what?

是的,我强烈建议阅读Framework Design guidelines良好的编程最佳方法。

+0

感谢您对最佳实践的指导...... – pghtech 2010-06-18 14:17:20

19

1)为什么我会想使用性能 代替领域(特别是当它 出现,我只是添加额外的 代码

你应该总是使用属性在可能情况下,他们的抽象直接访问到该字段(如果您不创建一个,则会为您创建)。即使财产除了设定价值之外别无他法,它仍然可以保护您。稍后将字段更改为属性是一项重大改变,因此如果您有公共字段并希望将其更改为公共属性,则必须重新编译最初访问该字段的所有代码。

2)承认使用 性质的任何提示,而不是将他们视为 简单的方法(与 该得到的异常;设置太明显),当 跟踪其他民族的代码?

我不能完全肯定你所问的,但跟踪过别人的代码时,你应该总是假设属性所做的不仅仅是获取和设置的值以外的东西。尽管在getter和setter中不要使用大量的代码是可以接受的,但是你不能仅仅假设它是一个属性,它会表现得很快。

3)经验的一般规则,当 涉及到良好的编程方法 关系时使用什么?

我总是使用属性来获取和设置方法,如果可能的话。这样我可以在以后添加代码,如果我需要检查该值是否在某个范围内,而不是空值等。不使用属性,我必须返回并将这些检查放在我直接访问该字段的每个位置。

0

属性允许您在使用它们时设置或获取值以外的其他值。最值得注意的是,它们允许您执行验证逻辑。

最佳实践是使任何暴露于公众的物品成为物业。这样,如果稍后更改set/get逻辑,则只需重新编译您的类,而不是每个与它相关的类。

6

1)有几个原因,您可能希望使用属性过场,这里只是一对夫妇:1)通过

具有以下

public string MyProperty { get; private set; } 

你正在属性“读只要”。没有人使用你的代码可以修改它的价值。有些情况下,这不是严格的(如果你的财产是一个列表),但这些是已知的并且有解决方案。

b)如果你决定你需要增加你的代码中使用财产的安全:

public string MyProperty 
{ 
    get { return _myField; } 
    set 
    { 
     if (!string.IsNullOrEmpty(value)) 
     { 
      _myField = value; 
     } 
    } 
} 

2)你可以告诉他们属性,因为他们没有()。编译器会告诉你是否尝试添加括号。

3)总是使用属性被认为是很好的做法。

+1

在VB.NET中,您可以将字段设置为只读! – 2010-06-18 13:37:27

+2

@Josh:你也可以在C#中:http://msdn.microsoft.com/en-us/library/acdd6hb7。aspx – LukeH 2010-06-18 13:45:28

+1

@Josh - 'readonly'意味着这个值不能在任何地方改变 - 即使是在同一个班级。使用私有setter属性意味着您可以修改类中的值,但是您的类的用户不能。 – ChrisF 2010-06-18 13:58:25

11

关于属性的好处之一是getter和setter可以有不同的访问级别。考虑这个:

public class MyClass { 

    public string MyString { get; private set; } 

    //...other code 
} 

此属性只能从内部,例如在构造函数中更改。阅读依赖注入。构造函数注入和属性注入都处理来自某种形式的外部配置的设置属性。那里有很多框架。如果您深入了解其中的一些内容,您将会对其性能和使用有很好的感受。依赖注入也可以帮助你解决关于良好实践的第三个问题。

在查看其他人的代码时,可以通过图标不同来判断是方法还是属性。另外,在Intellisence中,属性摘要的第一部分是Property。

1

我打算说属性(setters)是一个很棒的地方,可以引发像NotifyPropertyChanged这样的事件,但其他人却把我打败了。

考虑属性的另一个很好的理由:比方说,你使用工厂来构造一个具有默认构造函数的对象,并通过它的属性来准备对象。新建foo(){Prop1 =“bar”,Prop2 = 33,...};

但是,如果外部用户新增了您的对象,可能是有些属性需要它们以只读方式来看,并且无法设置(只有工厂应该可以设置它们)?你可以让setter成为内部的 - 当然,如果对象的类与工厂在同一个程序集中,这只能起作用。

还有其他的方法来实现这一目标,但使用属性和不同的访问知名度是一个很好的考虑,如果你正在做基于接口的开发,或者如果你暴露库给别人,等

5

虽然我绝对不喜欢直接向公众公开领域,还有一件事:领域不能通过接口暴露;属性可以。

+1

第一个理智的答案 – 2012-05-19 15:52:10

1

一个警告是,诸如“Threading.Interlocked.Increment”的东西可以与字段一起使用,但不能与属性一起使用。如果两个线程同时在SomeObject.LongIntegerField上调用Threading.Interlocked.Increment,则即使没有其他锁定,该值也会增加2。相比之下,如果两个线程同时对SomeObject.LongIntegerProperty调用Threading.Interlocked.Increment,那么该属性的值可能会增加2,或1,或-4,294,967,295,或者谁知道其他值(可以写入属性在这种情况下使用除一个或两个以外的锁定防止值,但无法写入以确保两个正确的增量)。

1

使用字段通常在私有类中实现,而不是与其他类共享数据。当我们希望我们的数据可以被其他类访问时,我们使用能够与其他类共享数据的属性,通过getset它们是访问方法Auto Properties,它们可以访问私有类中的数据,您也可以在同一个类中同时使用访问修饰符,从而允许类私有地将数据用作数据字段,并且同时将私有字段链接到属性这使得数据也可以被其他类访问,请看这个简单的例子:

private string _name; 
public string Name  
{ 
    get 
    { 
     return _name; 
    } 
    set 
    { 
     _name = value; 
    } 
} 

私有字符串_name仅供类使用,而Name属性可由同一名称空间中的其他类访问。