C# 3.0+ 中属性和字段的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/653536/
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 Property and Field in C# 3.0+
提问by p4bl0
I realize that it seems to be a duplicate of What is the difference between a Field and a Property in C#?but my question has a slight difference (from my point of view):
我意识到它似乎与C# 中的字段和属性有什么区别?但我的问题略有不同(从我的角度来看):
Once I know that
一旦我知道
- I will not use my class with "techniques that only works on properties" and
- I will not use validation code in the getter/setter.
- 我不会将我的课程与“仅适用于属性的技术”一起使用,并且
- 我不会在 getter/setter 中使用验证代码。
Is there any difference (except the style/future development ones), like some type of control in setting the property?
是否有任何区别(样式/未来开发的除外),例如设置属性时的某种类型的控件?
Is there any additional difference between:
是否有任何额外的区别:
public string MyString { get; set; }
and
和
public string myString;
(I am aware that, that the first version requires C# 3.0 or above and that the compiler does create the private fields.)
(我知道,第一个版本需要 C# 3.0 或更高版本,并且编译器确实创建了私有字段。)
采纳答案by Mark Ingram
Encapsulation.
封装。
In the second instance you've just defined a variable, in the first, there is a getter / setter around the variable. So if you decide you want to validate the variable at a later date - it will be a lot easier.
在第二个实例中,您刚刚定义了一个变量,在第一个实例中,变量周围有一个 getter/setter。因此,如果您决定要在以后验证变量 - 会容易得多。
Plus they show up differently in Intellisense :)
此外,它们在 Intellisense 中的显示方式不同:)
Edit:Update for OPs updated question - if you want to ignore the other suggestions here, the other reason is that it's simply not good OO design. And if you don't have a very good reason for doing it, alwayschoose a property over a public variable / field.
编辑:更新 OP 更新问题 - 如果您想忽略此处的其他建议,另一个原因是它根本不是好的 OO 设计。如果您没有充分的理由这样做,请始终选择公共变量/字段上的属性。
回答by Frederik Gheysels
The first one:
第一个:
public string MyString {get; set; }
is a property; the second one ( public string MyString
) denotes a field.
是财产;第二个 ( public string MyString
) 表示一个字段。
The difference is, that certain techniques (ASP.NET databinding for instances), only works on properties, and not on fields. The same is true for XML Serialization: only properties are serialized, fields are not serialized.
不同之处在于,某些技术(例如 ASP.NET 数据绑定)仅适用于属性,而不适用于字段。XML 序列化也是如此:只有属性被序列化,字段没有被序列化。
回答by Dustin Campbell
A couple quick, obvious differences
几个快速、明显的差异
A property can have accessor keywords.
public string MyString { get; private set; }
A property can be overridden in descendents.
public virtual string MyString { get; protected set; }
属性可以有访问器关键字。
public string MyString { get; private set; }
属性可以在后代中被覆盖。
public virtual string MyString { get; protected set; }
回答by AnthonyWJones
The fundamental difference is that a field is a position in memory where data of the specified type is stored. A property represents one or two units of code that are executed to retrieve or set a value of the specified type. The use of these accessor methods is syntactically hidden by using a member that appears to behave like a field (in that it can appear on either side of an assignment operation).
根本区别在于,字段是内存中存储指定类型数据的位置。一个属性代表一个或两个代码单元,它们被执行以检索或设置指定类型的值。这些访问器方法的使用在语法上通过使用一个看起来像一个字段的成员(因为它可以出现在赋值操作的任一侧)而被隐藏起来。
回答by Erik Funkenbusch
Properties and Fields may, in many cases, seem similar, but they are not. There are limitations to properties that do not exist for fields, and vice versa.
在许多情况下,属性和字段可能看起来相似,但实际上并非如此。对于字段不存在的属性存在限制,反之亦然。
As others have mentioned. You can make a property read-only or write-only by making it's accessor private. You can't do that with a field. Properties can also be virtual, while fields cannot.
正如其他人所提到的。您可以通过将访问器设为私有来将属性设为只读或只写。你不能用一个字段来做到这一点。属性也可以是虚拟的,而字段则不能。
Think of properties as syntactic sugar for getXXX()/setXXX() functions. This is how they are implemented behind the scenes.
将属性视为 getXXX()/setXXX() 函数的语法糖。这就是它们在幕后实现的方式。
回答by Brian Rasmussen
Fields and properties look the same, but they are not. Properties are methods and as such there are certain things that are not supported for properties, and some things that may happen with properties but never in the case of fields.
字段和属性看起来相同,但实际上不同。属性是方法,因此属性不支持某些事情,属性可能会发生一些事情,但不会在字段的情况下发生。
Here's a list of differences:
以下是差异列表:
- Fields can be used as input to
out/ref
arguments. Properties can not. - A field will always yield the same result when called multiple times (if we leave out issues with multiple threads). A property such as
DateTime.Now
is not always equal to itself. - Properties may throw exceptions - fields will never do that.
- Properties may have side effects or take a really long time to execute. Fields have no side effects and will always be as fast as can be expected for the given type.
- Properties support different accessibility for getters/setters - fields do not (but fields can be made
readonly
) - When using reflection the properties and fields are treated as different
MemberTypes
so they are located differently (GetFields
vsGetProperties
for example) - The JIT Compiler may treat property access very differently compared to field access. It may however compile down to identical native code but the scope for difference is there.
- 字段可以用作
out/ref
参数的输入。属性不行。 - 一个字段在多次调用时总是会产生相同的结果(如果我们忽略多线程的问题)。诸如此类的属性
DateTime.Now
并不总是等于自身。 - 属性可能会抛出异常 - 字段永远不会这样做。
- 属性可能有副作用或需要很长时间才能执行。字段没有副作用,并且对于给定类型将始终如预期的那样快。
- 属性支持 getter/setter 的不同可访问性 - 字段不支持(但可以创建字段
readonly
) - 使用反射时,属性和字段被视为不同,
MemberTypes
因此它们的位置不同(例如GetFields
vsGetProperties
) - 与字段访问相比,JIT 编译器可能会以非常不同的方式处理属性访问。然而,它可能会编译为相同的本机代码,但存在差异的范围。
回答by Zoran Horvat
Accessors are more than fields. Others have already pointed out several important differences, and I'm going to add one more.
访问器不仅仅是字段。其他人已经指出了几个重要的差异,我将再添加一个。
Properties take part in interface classes. For example:
属性参与接口类。例如:
interface IPerson
{
string FirstName { get; set; }
string LastName { get; set; }
}
This interface can be satisfied in several ways. For example:
可以通过多种方式满足此接口。例如:
class Person: IPerson
{
private string _name;
public string FirstName
{
get
{
return _name ?? string.Empty;
}
set
{
if (value == null)
throw new System.ArgumentNullException("value");
_name = value;
}
}
...
}
In this implementation we are protecting both the Person
class from getting into an invalid state, as well as the caller from getting null out from the unassigned property.
在这个实现中,我们保护Person
类不进入无效状态,以及调用者从未分配的属性中获取空值。
But we could push the design even further. For example, interface might not deal with the setter. It is quite legitimate to say that consumers of IPerson
interface are only interested in getting the property, not in setting it:
但我们可以进一步推动设计。例如,接口可能不处理 setter。可以说IPerson
接口的消费者只对获取属性感兴趣,而不对设置它感兴趣:
interface IPerson
{
string FirstName { get; }
string LastName { get; }
}
Previous implementation of the Person
class satisfies this interface. The fact that it lets the caller also set the properties is meaningless from the point of view of consumers (who consume IPerson
). Additional functionality of the concrete implementation is taken into consideration by, for example, builder:
Person
该类的先前实现满足此接口。从消费者(谁消费IPerson
)的角度来看,它让调用者也设置属性这一事实毫无意义。例如,builder 会考虑具体实现的附加功能:
class PersonBuilder: IPersonBuilder
{
IPerson BuildPerson(IContext context)
{
Person person = new Person();
person.FirstName = context.GetFirstName();
person.LastName = context.GetLastName();
return person;
}
}
...
void Consumer(IPersonBuilder builder, IContext context)
{
IPerson person = builder.BuildPerson(context);
Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
}
In this code, consumer doesn't know about property setters - it is not his business to know about it. Consumer only needs getters, and he gets getters from the interface, i.e. from the contract.
在这段代码中,消费者不知道属性设置器 - 了解它不是他的事。消费者只需要 getter,他从接口中获取 getter,即从合约中获取。
Another completely valid implementation of IPerson
would be an immutable person class and a corresponding person factory:
另一个完全有效的实现IPerson
是一个不可变的 person 类和一个相应的 person 工厂:
class Person: IPerson
{
public Person(string firstName, string lastName)
{
if (string.IsNullOrEmpty(firstName) || string.IsNullOrEmpty(lastName))
throw new System.ArgumentException();
this.FirstName = firstName;
this.LastName = lastName;
}
public string FirstName { get; private set; }
public string LastName { get; private set; }
}
...
class PersonFactory: IPersonFactory
{
public IPerson CreatePerson(string firstName, string lastName)
{
return new Person(firstName, lastName);
}
}
...
void Consumer(IPersonFactory factory)
{
IPerson person = factory.CreatePerson("John", "Doe");
Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
}
In this code sample consumer once again has no knowledge of filling the properties. Consumer only deals with getters and concrete implementation (and business logic behind it, like testing if name is empty) is left to the specialized classes - builders and factories. All these operations are utterly impossible with fields.
在此代码示例中,消费者再次不知道填充属性。消费者只处理 getter 和具体的实现(以及它背后的业务逻辑,比如测试 name 是否为空)留给专门的类 - 构建器和工厂。所有这些操作对于字段都是完全不可能的。
回答by BradleyDotNET
There is one other important difference between fields and properties.
字段和属性之间还有另一个重要区别。
When using WPF, you can only bind to public properties. Binding to a public field will notwork. This is true even when not implementing INotifyPropertyChanged
(even though you always should).
使用 WPF 时,您只能绑定到公共属性。绑定到公共领域将不会工作。即使不实施也是如此INotifyPropertyChanged
(即使您总是应该这样做)。
回答by user1849310
You should always use properties instead of fields for any public fields.This ensures that your library has the ability to implement encapsulation for any field if required in future without breaking the existing codes.If you replace the fields with properties in existing libraries then all the dependent modules using your library also need to be rebuilt.
对于任何公共字段,您应该始终使用属性而不是字段。这确保您的库能够在将来需要时为任何字段实现封装,而不会破坏现有代码。如果您用现有库中的属性替换字段,那么所有使用你的库的依赖模块也需要重建。
回答by maytham-???????
Among other answers and examples, I think this example is useful in some situations.
在其他答案和示例中,我认为这个示例在某些情况下很有用。
For example let say you have a OnChange
property
like following:
例如,假设您有以下类似内容:OnChange
property
public Action OnChange { get; set; }
If you want to use delegates than you need to change it OnChange
to field
like this:
如果您想使用委托,则需要将其更改OnChange
为field
如下所示:
public event Action OnChange = delegate {};
In such situation we protect our field from unwanted access or modification.
在这种情况下,我们保护我们的领域免受不必要的访问或修改。