为什么我们在一个类中创建一个私有变量,然后在c#中的以下行中创建一个公共属性? 此外,我没有得到获取和设置属性的概念。
我的意思是为什么我们这样做
public class MyClass
{
private string _myProperty;
public string MyProperty
{
get
{ return _myProperty; }
set
{ _myProperty = value; }
}
或者
public class MyClass
{
public string MyProperty {get;set;}
}
我的问题与此问题非常类似: Why do we need to create class variables to get and set a property?
以上主题似乎没有解决我的问题。有人请详细说明:
问题的答案可能太长了。但即使你花费宝贵的时间来恰当地解释一个问题,我也不仅仅是有义务。在此先感谢:)
答案 0 :(得分:7)
为什么先创建私有变量然后再创建属性 它?为什么不一步?
如果要在设置属性之前进行某种验证,则使用私有变量,或者基本上抽象出类中有关该属性的内容。例如,如果您希望给定变量在范围内:
private int foo;
public int Foo
{
get { return foo; }
set
{
if (value < 0 || value > 10)
{
throw new ArgumentOutOfRangeException(value);
}
foo = value;
}
}
我们需要'获得'和'设置'以及为什么有两种方法可以使用它?
C#-3.0带来Auto-Properties,因为MSFT看到很多人使用属性“有一天我想要验证我的变量或改变内部实现的可能性”。公开属性而不是变量允许您稍后添加任何代码验证,而不会破坏与属性的任何调用者的现有“契约”。
@JonSkeet很好地拼凑出来,在他的C# In Depth(感谢@Sriram)中表现平平:
- 带有属性的细粒度访问控制。
- 需要它是公开获取的,但实际上只希望它设置为受保护的访问权限?没问题(从C#2开始,至少)。
- 每当值发生变化时,想要进入调试器吗?只需在setter中添加一个断点即可。
- 想要记录所有访问权限吗?只需将日志添加到getter。
- 属性用于数据绑定;字段不是。
答案 1 :(得分:4)
将字段设为私有并将其作为属性公开,可以提供控制set和get操作的类功能,这在不同的场景中非常有用。
该类可以在将提供的数据存储到字段之前对其进行验证:
class WeatherInfo {
private static readonly int minDegree = -273;
private static readonly int maxDegree = 75;
private int degree;
public int Degree {
get {
return this.degree;
}
set {
if (value < minDegree || value > maxDegree) {
throw new ArgumentOutOfRangeException();
}
}
}
..
..
}
在某些情况下,对象的字段可能没有有意义的值。提供getter方法,允许对象通知它的客户端。
class User {
private DateTime loginTime;
private bool loggedIn;
..
..
public DateTime LoginTime {
get {
if (!this.loggedIn) {
throw new InvalidOperationException();
}
return loginTime;
}
}
}
使用属性而不是字段的另一个好处是它允许对象限制对字段的访问。在前面的例子中,我们有一个没有setter的方法。此方法的另一个用途是限制对setter的访问。
class Customer {
private string name;
private string family;
private string nameFamily;
public string name {
get {
return this.name;
}
private set {
if (!string.Equals(name, value)) {
this.name = value;
this.UpdateNameFamily();
}
}
}
private void UpdateNameFamily() {
this.nameFamily = string.Format("{0} {1}", this.name, this.family);
}
..
..
}
正如您所看到的,这种方法的好处是它允许类在属性从类内部更改时执行某些操作。
用于引发XXXXChanged事件的常见模式是检查setter中的值并在事件发生更改时引发事件:
class Question {
public event EventHandler AnsweredChanged;
private bool isAnswered;
..
..
public bool IsAnswered {
get {
return this.isAnswered;
}
set {
if (this.isAnswered != value) {
this.OnIsAnsweredChanged();
}
}
}
private void OnIsAnsweredChanged() {
if (this.AnsweredChanged!= null) {
this.AnsweredChanged(this, EventArgs.Empty);
}
}
}
这种方法的另一个常见用途是实现INotifyPropertyChanged接口。
即使您不需要属性可以实现的任何内容,并且您拥有无逻辑类,但最好不要将类字段暴露给类的外部世界。在这种情况下,您可以简单地使用自动属性作为遵循最佳实践的快捷方式,而无需直接定义字段。
class UserModel {
public string Username {
get;
set;
}
public DateTime Birthdate {
get;
set;
}
..
..
}
答案 2 :(得分:3)
你的两个例子都是等价的。第二个是第一个的语法糖。
Property的原因是在类的内部状态上创建抽象。例如,如果您使用公共字段,则在没有更改类的接口的情况下,您没有机会更改它。使用属性隐藏实现,其余代码不会改变任何内容。 例如:
bin/cake bake model Articles
我想更改实现细节以直接从db
存储/检索值public class MyClass
{
public string MyProperty {get;set;}
}
正如您所看到的,实现发生了巨大变化,但类接口仍然相同。
答案 3 :(得分:2)
班级的内部逻辑应该与外界保持隐藏。
假设您需要一个可以从外部访问的字段,但只能从类内部设置,没有属性,您将不得不这样做:
public class Example
{
private String _data;
public String GetData()
{
return _data;
}
}
使用属性,你可以用这种方式做同样的事情:
public class Example
{
private String _data;
public String Data { get; private set}
}
您缩短您的代码并使其更干净并且您可以完全控制字段可访问性,但是属性具有很多优点。例如,假设您的私有字段需要一些逻辑,假设在字段被分配之前从外部访问该属性。
请考虑以下示例:
public class Example
{
private MyCustomClass _data;
public MyCustomClass Data { get { return _data }; private set { _data = value;}}
}
如果尚未分配_data,如果您尝试使用它,您将在代码中的某处获得null异常,但您可以像这样避免它来实现某些逻辑:
public class Example
{
private MyCustomClass _data;
public MyCustomClass Data
{
get
{
if(_data == null)
_data = new MyCustomClass();
return _data;
}
private set { _data = value;} }
}
因此您可以实施 逻辑以及属性。
此外,请记住,当您创建这样的属性时
public class Example
{
public String MyData{ get; set;}
}
实际上,当你编译它时,编译器会把它翻译成这样的东西:
public class Example
{
private String _myData;
public String MyData{ get {return _myData}; set { _myData = value}}
}
最后假设将来你需要将设置值的逻辑更改为该字段,如果你使用过公共字段,你将需要做很多工作,但如果你使用了属性,你只需要改变财产的逻辑,你这样做,所以可维护性也是一个很好的属性!
修改强>
关于 Binding 的大多数框架使用绑定prupose