C# 自动实现的getter和setter与公共字段

C# 自动实现的getter和setter与公共字段,c#,oop,properties,field,C#,Oop,Properties,Field,我看到很多C#类的示例代码都是这样做的: public class Point { public int x { get; set; } public int y { get; set; } } 或者,在旧代码中,使用显式的私有支持值,并且没有新的自动实现属性: public class Point { private int _x; private int _y; public int x { get { return _x; }

我看到很多C#类的示例代码都是这样做的:

public class Point {
    public int x { get; set; }
    public int y { get; set; }
}
或者,在旧代码中,使用显式的私有支持值,并且没有新的自动实现属性:

public class Point {
    private int _x;
    private int _y;

    public int x {
        get { return _x; }
        set { _x = value; }
    }

    public int y {
        get { return _y; }
        set { _y = value; }
    }
}
我的问题是为什么。执行上述操作和仅将这些成员公开在下面这样的字段之间有什么功能上的区别吗

public class Point {
    public int x;
    public int y;
}

明确地说,当您需要对底层数据进行一些转换时,我理解getter和setter的价值。但是,在您只是传递值的情况下,它似乎不必要地冗长。

它封装了这些成员的设置和访问。如果从现在开始,代码开发人员在访问或设置成员时需要更改逻辑,则可以在不更改类的约定的情况下完成此操作。

您永远不知道以后是否可能不需要对数据进行翻译。如果你把你的成员藏起来,你就做好了准备。类的用户不会注意到您是否添加了翻译,因为界面保持不变。

最大的区别在于,如果更改内部结构,您仍然可以保持getter和setter不变,在不伤害API用户的情况下更改其内部逻辑。

以后更改此逻辑也简单得多:

public int x { get; private set; }
我倾向于同意(这似乎是不必要的冗长),尽管这一直是我们团队尚未解决的问题,因此我们的编码标准仍然坚持所有类的详细属性


几年前处理过这个问题。他回顾性地指出,最重要的一点是,从字段更改为属性是代码中的一个重要部分;任何使用它的东西都必须重新编译才能使用新的类接口,因此,如果任何超出您控制范围的东西正在使用您的类,您可能会遇到问题。

如果您必须更改在这种情况下获取x和y的方式,您可以稍后添加属性。这是我最困惑的。如果使用公共成员变量,以后可以很容易地将其更改为属性,如果需要在内部存储值,可以使用名为_x和_y的私有变量

这个想法是,即使底层数据结构需要更改,类的公共接口也不需要更改

C#有时会以不同的方式处理属性和变量。比如你。因此,如果您出于某种原因需要更改数据结构,并且您使用的是公共变量,现在您需要使用属性,那么您的接口将必须更改,现在访问属性x的代码可能不再像它是变量x时那样编译:

Point pt = new Point();
if(Int32.TryParse(userInput, out pt.x))
{
     Console.WriteLine("x = {0}", pt.x);
     Console.WriteLine("x must be a public variable! Otherwise, this won't compile.");
}

从一开始就使用属性可以避免这种情况,您可以随意调整底层实现,而无需中断客户端代码。

AFAIK生成的CIL接口是不同的。如果您将公共成员更改为属性,那么您正在更改它的公共接口,并且需要重新生成使用该类的每个文件。如果您只更改getter和setter的实现,则不需要这样做。

在绑定和序列化方面,还需要考虑更改对公共成员的影响。这两种方法通常都依赖于公共属性来检索和设置值。

也许仅仅是将字段公开,您就可以找到一个更合适的方法


善意的问候原则上是不好的(它们是一种糟糕的OO气味——我不想说它们是反模式的,因为它们有时确实是必要的)

不,在技术上没有区别,当我现在真的想共享对一个对象的访问时,我偶尔会公开它,而不是添加一个getter

setter和getter被“出售”的方式是,您可能需要知道有人正在获取或更改一个值——这只适用于原语


属性包对象(如DAO、DTO和显示对象)被排除在该规则之外,因为它们不是真正意义上的“OO设计”对象。(你不会想到向DAO“传递消息”,它只是一堆属性/值对)。

Setter和Getter使你能够添加额外的抽象层,在纯OOP中,你应该始终通过对象提供给外部世界的接口访问对象

考虑以下代码,这将在asp.net中为您节省时间,如果没有setter和getter提供的抽象级别,这是不可能的:

class SomeControl
{

private string _SomeProperty  ;
public string SomeProperty 
{
  if ( _SomeProperty == null ) 
   return (string)Session [ "SomeProperty" ] ;
 else 
   return _SomeProperty ; 
}
}

因为自动实现的getter对属性和实际的私有存储变量使用相同的名称。你将来如何改变它?我认为所说的要点是使用auto-implemented而不是field,以便在将来需要向getter和setter添加逻辑时可以对其进行更改

private string _x;

public string x { 
    get {return _x}; 
    set {
        if (Datetime.TryParse(value)) {
            _x = value;
        }
    }; 
}
例如:

public string x { get; set; }
例如,您已经多次使用x,并且不想破坏代码

如何更改自动getter setter。。。例如,对于setter,您只允许设置有效的电话号码格式。。。如何更改代码以便只更改类

我的想法是添加一个新的私有变量,并添加相同的x getter和setter

private string _x;

public string x { 
    get {return _x}; 
    set {
        if (Datetime.TryParse(value)) {
            _x = value;
        }
    }; 
}

这就是使其灵活的意思吗?

此外,您可以在getter和setter上设置断点,但不能在字段上设置断点

还值得注意的是,您不能将自动属性设置为只读,也不能对其进行内联初始化。这两件事我都希望在未来的.NET版本中看到,但我相信在.NET4.0中两者都做不到

这些天来,我只在类实现INotifyPropertyChanged时使用带有属性的支持字段,并且在属性更改时需要触发OnPropertyChanged事件

此外,在这些情况下,当从构造函数传入值时,我直接设置支持字段(无需尝试并启动OnPropertyChangedEvent(此时为NULL)