C# 成员变量和成员属性的区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2283026/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Difference between member variable and member property?
提问by Xaisoft
There are situations where I declare member variables at the top of my class and then also declare a property to access or set that member variable, but I ask myself if the property is necessary if it variable is only going to be accessed and set from within the class and no where else, so what is the advantage of using a property to access and set a member variable instead of just doing it directly to the member variable itself. Here is an example:
在某些情况下,我在类的顶部声明了成员变量,然后还声明了一个属性来访问或设置该成员变量,但我会问自己,如果变量只能从内部访问和设置,是否需要该属性类而不是其他任何地方,那么使用属性来访问和设置成员变量而不是直接对成员变量本身进行访问和设置有什么好处。下面是一个例子:
public class Car
{
int speed; //Is this sufficient enough if Car will only set and get it.
public Car(int initialSpeed)
{
speed = initialSpeed;
}
//Is this actually necessary, is it only for setting and getting the member
//variable or does it add some benefit to it, such as caching and if so,
//how does caching work with properties.
public int Speed
{
get{return speed;}
set{speed = value;}
}
//Which is better?
public void MultiplySpeed(int multiply)
{
speed = speed * multiply; //Line 1
this.Speed = this.Speed * multiply; //Line 2
//Change speed value many times
speed = speed + speed + speed;
speed = speed * speed;
speed = speed / 3;
speed = speed - 4;
}
}
In the above, if I don't have the property Speed to set and get the variable speed, and I decide to change int speed to int spd, I will have to change speed to spd everywhere it is used, however, if I use a property such as Speed to set and get speed, I will just have to change speed to spd in the get and set of the property, so in my MutilplySpeed method, stuff like above this.Speed = this.Speed + this.Speed + this.Speed will not break.
在上面,如果我没有属性 Speed 来设置和获取可变速度,并且我决定将 int speed 更改为 int spd,我将不得不在任何使用它的地方将 speed 更改为 spd,但是,如果我使用设置和获取速度之类的属性,我只需要在属性的获取和设置中将速度更改为 spd,因此在我的 MutilplySpeed 方法中,类似上面的内容 this.Speed = this.Speed + this.Speed +这个。速度不会破。
采纳答案by Fredrik M?rk
If the variable is private
, I will often not create a property for it. If it is, in any way, exposed outside the type, I always expose it through a property for different reasons:
如果变量是private
,我通常不会为它创建属性。如果它以任何方式暴露在类型之外,我总是出于不同的原因通过属性公开它:
- It may not be necessary today, but if it becomes necessary later it's a breaking change
- Databinding works only on properties, not on fields (I think, not a big databinding user)
- It allows to insert validations, logging, breakpoints when accessing the value
- 今天可能没有必要,但如果以后有必要,那就是一个突破性的变化
- 数据绑定仅适用于属性,不适用于字段(我认为,不是大数据绑定用户)
- 它允许在访问值时插入验证、日志记录、断点
Also, if the field is exposed through a property, I always access it through the property, even within the class.
此外,如果该字段通过属性公开,我总是通过该属性访问它,即使在类中也是如此。
Update
In response to your updated code samples: there are a number of things to consider around the code design here.
更新
响应您更新的代码示例:此处围绕代码设计需要考虑许多事项。
- Readability vs. Speed
- "Atomicity"
- Other side effects
- 可读性与速度
- “原子性”
- 其他副作用
One typical piece of advice (that I find very good) is "write for clarity, test for performance". That means that when you write your code, your first concern should be whether it is clear what the code does when looking at it. This is often (but not always) more important than the raw speed of the code. Write speed optimizations when you have established where you gain it. Accessing a property will be a tad slower than reading the field directly, but in most cases, the difference will be negligible (if at all measurable).
一个典型的建议(我觉得非常好)是“为了清晰而编写,为了性能而测试”。这意味着当您编写代码时,您首先要考虑的是在查看代码时是否清楚代码的作用。这通常(但并非总是)比代码的原始速度更重要。当您确定获得它的位置时,编写速度优化。访问属性会比直接读取字段慢一点,但在大多数情况下,差异可以忽略不计(如果可以测量的话)。
Atomicitymay be an issue. Given your code sample, we have the field speed
, that is publicly exposed through the property Speed
. If the method MultiplySpeed
needs to perform several updates to the value, those intermediate values will be available through the Speed
property at different times while the calculation is ongoing. This is true regardless of whether you update the field directly or through the property. In cases like this it is perhaps better to first put the value into a local variable, use that for the calculations and assign the value of that variable back to the property when done.
原子性可能是一个问题。鉴于您的代码示例,我们有speed
通过属性公开公开的字段Speed
。如果该方法MultiplySpeed
需要对值执行多次更新,则这些中间值将Speed
在计算进行的不同时间通过属性提供。无论您是直接更新字段还是通过属性更新字段,都是如此。在这种情况下,最好先将值放入局部变量中,将其用于计算,并在完成后将该变量的值分配回属性。
Lastly, other side effects. It could be that changing the value of Speed
should raise an event (such as SpeedChanged
). In cases like that, it is also probably a good idea not to make the update until the calculation is done.
最后,其他副作用。可能是更改 的值Speed
应该引发事件(例如SpeedChanged
)。在这种情况下,在计算完成之前不要进行更新也可能是一个好主意。
I like to think about the property as a contractand the field as implementation. Anybody (except for the core of my type) that needs the value should use the contract. Relying on the implementation should be done only if there are good reasons to bypass the contract.
我喜欢将财产视为合同,将领域视为实施。任何需要价值的人(除了我的核心类型)都应该使用合约。只有在有充分的理由绕过合同的情况下,才应该依赖实施。
And yes, if you encapsulate the access to the field in the property, naturally changing the name of the field will require less updates (and perhaps also the name of the field becomes less important).
是的,如果您将对该字段的访问封装在属性中,自然地更改该字段的名称将需要较少的更新(并且该字段的名称可能也变得不那么重要)。
I hope that makes sense, and is not too much off topic ;)
我希望这是有道理的,并且不会离题太多;)
回答by JonH
One thing you forgot to mention, properties will help you out when you extend your class.
If your class is properly designed your variables inside the base class should be private
. Without the actual properties public
properties that is. You would have no way to access these private variables from within your extended class. We are talking public vs private and I am not including protected for a reason :).
您忘记提及的一件事是,属性将在您扩展类时帮助您。如果您的类设计正确,则基类中的变量应该是private
. 没有实际属性public
属性。您将无法从扩展类中访问这些私有变量。我们正在谈论公共与私人,我不包括受保护的原因:)。
Just some notes worth mentioning:
只是一些值得一提的注意事项:
- properties aide when a class is extended
- properties to me make the code a bit more readable (in addition this.privateVariable verson PublicPropertyVariableName)
- properties can ensure readonly, private sets, public gets etc (much more readable to other programmers). Consider a case where an IDentifier needs a public get but a private set
- Personally to me too many gets / sets seems to complicate code, makes code less readable, too much extra unnecessary syntax
- inheritance / extending to an extended class does not allow you to inherit private variables, properties are the answer. (again no mention of protected here, that is a different story)
- To me even if the class has a private variable, my class methods still use the property to access or use that private variable
- Don't forget about validation, it makes it much easier to validate especially readability wise.
- 扩展类时的属性助手
- 属性对我来说使代码更具可读性(此外 this.privateVariable 版本 PublicPropertyVariableName)
- 属性可以确保只读、私有集、公共获取等(对其他程序员更具可读性)。考虑一个标识符需要公共获取但需要私有集合的情况
- 就我个人而言,太多的 get/sets 似乎使代码复杂化,使代码可读性降低,过多的额外不必要的语法
- 继承/扩展到扩展类不允许您继承私有变量,属性就是答案。(这里再次没有提到受保护,那是另一回事)
- 对我来说,即使类有一个私有变量,我的类方法仍然使用该属性来访问或使用该私有变量
- 不要忘记验证,它使验证尤其是可读性更容易。
These are just some common things (my 2 cents though on most of them).
这些只是一些常见的东西(我的 2 美分虽然在其中大部分)。
回答by Ikke
Things like validation can be covered at one place. The member is encapsulated, and you want have to worry about validation and other things from the rest of your class.
诸如验证之类的事情可以在一处涵盖。该成员是封装的,您需要担心其他类的验证和其他事情。
In your current scenario it doesn't really make a difference, but when you need to change the variable or need to add behavior, it's easier when you use properties, because you only have one place where you need to change it.
在您当前的场景中,它并没有真正产生影响,但是当您需要更改变量或需要添加行为时,使用属性会更容易,因为您只有一个地方需要更改它。
回答by Pharabus
it does not add caching but it does allow a consistent interface.
它不添加缓存,但它允许一致的接口。
imagine you had to ammend speed by adding a constant to it in future. using the member variable would be difficult where as the property allows this manipulation.
想象一下,您将来必须通过向其添加常量来修改速度。在属性允许这种操作的情况下,使用成员变量会很困难。
Also internally in the class you should again access the property for consistency (imagine the above scenario where you had a class that accessed the member variable direct).
同样在类内部,您应该再次访问属性以保持一致性(想象上面的场景,您有一个直接访问成员变量的类)。
回答by pdr
The only genuine reason I know of is if the field is being accessed from outside of the assembly. In that case, should you want to add light functionality to that field (maybe set a Dirty flag or validate a change) you have to change it to a property which changes the way it is viewed by the calling assembly, which will also need rebuilding. In very rare cases, you might find that you don't have control over that assembly, then you have a problem.
我所知道的唯一真正原因是是否从程序集外部访问该字段。在这种情况下,如果您想向该字段添加轻量级功能(可能设置一个脏标志或验证更改),您必须将其更改为一个属性,该属性更改调用程序集查看它的方式,这也需要重建. 在极少数情况下,您可能会发现您无法控制该程序集,然后就会出现问题。
Don't let the OO zealots tell you that it's philsophically wrong to use public fields, although I might agree that auto-properties make the argument somewhat moot.
不要让面向对象的狂热分子告诉您使用公共字段在哲学上是错误的,尽管我可能同意自动属性使论点有点没有实际意义。
回答by Don Kirkby
I agree with Frederik'sanswer. One thing that makes it slightly less work to follow his advice is to use automatic properties. Those are just properties that automatically generate the standard getter/setter logic. You don't get any validation, but you can always replace the automatic property with a standard one later. This replacement is not a breaking change.
我同意弗雷德里克的回答。使遵循他的建议的工作稍微减少的一件事是使用自动属性。这些只是自动生成标准 getter/setter 逻辑的属性。您不会得到任何验证,但您可以随时用标准属性替换自动属性。这种替换不是破坏性的变化。
Here I've replaced the Speed property in your example with an automatic property. Notice that the member variable disappears and your class mustaccess it through the property.
在这里,我用自动属性替换了示例中的 Speed 属性。请注意,成员变量消失了,您的类必须通过属性访问它。
public class Car
{
public Car(int initialSpeed)
{
Speed = initialSpeed;
}
public int Speed { get; set; }
public void MultiplySpeed(int multiply)
{
Speed *= multiply;
}
}
You can also use another flavour called "get with private set". This means that the getter is public, but the setter is private. You define it like this:
您还可以使用另一种称为“使用私有集获取”的风格。这意味着 getter 是公开的,而 setter 是私有的。你这样定义它:
public int Speed { get; private set; }
As for your question about the this.
prefix, it's usually irrelevant. The only time it matters is when you've defined a method parameter or local variable with the same name as a member variable. Then you can use this
to access the member variable.
至于你关于this.
前缀的问题,它通常是无关紧要的。唯一重要的是当您定义了与成员变量同名的方法参数或局部变量时。然后就可以使用this
访问成员变量了。
回答by Jeff Hornby
The fact is, there is not a lot of difference between a publicly declared field and a public property with a private backing store if there is no extra logic. That being said, it is still considered best practice to use properties.
事实是,如果没有额外的逻辑,公开声明的字段和具有私有后备存储的公共属性之间没有太大区别。话虽如此,使用属性仍然被认为是最佳实践。
And before everybody jumps on me about extensibility, remember that if you do later need to add functionality, you can keep the name with the property and introduce a new name for the backing store so it's not a breaking change.
在每个人都向我提出可扩展性之前,请记住,如果您以后确实需要添加功能,您可以将名称保留在属性中,并为后备存储引入一个新名称,这样就不会造成重大更改。
回答by Christopher Hume
In my opinion the language design is broken. There should not be two ways of doing things that have so much semantic overlap. Properties/Fields should have seamlessly provided the benefits of eaither approach depending on how they are used. If the program makes minimal use of Property features they should act the same way as fields. There should furthermore not be a need to declare empty get; and set; methods in this case. The differences strike me as artificial.
在我看来,语言设计被打破了。不应该有两种处理方式有如此多的语义重叠。属性/字段应该根据它们的使用方式无缝地提供任何一种方法的好处。如果程序对属性功能的使用最少,它们的行为方式应与字段相同。此外,不需要声明空 get;并设置;在这种情况下的方法。这些差异让我觉得是人为的。
It's a great language; and pretty clean for the most part. That doesn't mean it shouldn't be improved upon "next time".
这是一种很棒的语言;大部分都非常干净。这并不意味着它不应该在“下次”时改进。