C#自动属性与正常字段

C#自动属性与正常字段,c#,automatic-properties,C#,Automatic Properties,在这个例子中,Foo.Something和Bar.Something之间有什么有效的区别吗 class Foo { public string Something; } class Bar { public string Something{get; set;} } class Program { static void Main(string[] args) { var MyFoo = new Foo(); MyFoo.Som

在这个例子中,Foo.Something和Bar.Something之间有什么有效的区别吗

class Foo
{
    public string Something;
}

class Bar
{
    public string Something{get; set;}
}

class Program
{
    static void Main(string[] args)
    {
        var MyFoo = new Foo();
        MyFoo.Something = "Hello: foo";
        System.Console.WriteLine(MyFoo.Something);

        var MyBar = new Bar();
        MyBar.Something = "Hello: bar";
        System.Console.WriteLine(MyBar.Something);
        System.Console.ReadLine();
    }
}
看来他们的行为完全一样。如果没有,为什么不使用Foo中的普通字段? 在java中,我们使用setter可以在不破坏代码的情况下强制执行新的不变量,并使用getter返回安全数据,但在c中,您始终可以将Foo重写为:

class Foo
{
    private string _Something;
    public string Something
    {
        get { 
            //logic
            return _Something; 
            }
        set { 
            //check new invariant
            _Something = value; 
            }
    }
}

而且旧代码不会被破坏。

属性的getter和setter(包括自动的)具有方法调用成本。应避免使用公共字段,以便在访问时保持干净。

Foo。Something
是一个字段,
栏。Something
是一个自动实现的属性。这是一个巨大的差异

您可以使用与字段相同的方式访问属性,但在访问属性时,会在内部调用set/get方法

因此,当您说
myBar.Something=“asdf”
时,C编译器将其转换为对setter方法的调用:
myBar.set\u Something(“asdf”)
。setter和getter方法会自动为您生成,以及实际值的支持字段

通过使用get和set方法将
Foo.Something
更改为属性,您正在破坏二进制兼容性,这意味着您必须重新编译使用
Foo.Something
的所有程序集,而它仍然是一个字段

看来他们的行为完全一样

不,他们没有

  • 字段不能用于数据绑定(至少在某些绑定实现中)
  • 以后可以为属性添加更多逻辑,而不破坏源代码或二进制兼容性
  • 属性不能通过引用传递
  • 不能向自动实现的属性添加初始值设定项
  • 他们在反思方面显然会有所不同
  • 从理论上讲,属性在逻辑上是API的一部分,而字段是实现细节
在c语言中,您可以随时将Foo重写为:[……]

如果你不关心二进制或源代码的兼容性,你可以。在某些情况下,这真的不是一个问题——在其他情况下,这是一个非常非常重要的问题。为什么不从一开始就选择公开API而不是实现细节呢?这不像在代码中添加
{get;set;}
会增加很多混乱

有关详细信息,请参见我的。

1)您可以添加专用访问器以获取或设置并控制对属性的访问

public object MyProp {get; private set;}
你可以在任何地方阅读道具,但只能在课堂内写作

2) 您可以将一些逻辑连接到读/写属性。在现场的情况下,你不能做任何额外的事情


3) 不能序列化字段

公共字符串{get;set;}
只是语法糖;编译器实际上将其扩展为方法。因此,让所有
get;设置字段到处都是,只是为了它。

你也可以用普通属性来做这件事。@Aschratt是的,但用字段你不能。当然,您可以使用字段指定
readonly
,但这比
private
setter要严格一些。对不起,我想问题是关于标准属性和自动属性之间的区别…:)没有恶意!你:应该避免使用公共字段我想公共
只读
字段可以吗?BCL使用它们。当然,这与原始问题无关。@JeppeStigNielsen我想是的。@JeppeStigNielsen:BCL很少使用只读实例字段。常数(即使是非常数常数,如果你明白我的意思的话)是另一回事。@JonSkeet我想你是对的。例如,
KeyValuePair
不使用
readonly
实例字段,它只使用
get
实例属性(不过,反射找不到
private
setters)。自动属性不能有(相当于)字段初始值设定项。例如,如果您最初想要
Something=“initial”
属性,则必须使实例构造函数显式,并在该构造函数的主体中写入赋值(或所有构造函数,除非它们使用
:此(…)
语法相互“链接”)。Jon Skeet走进一个问题,4票以上。@JeppeStigNielsen:对,对。@EaterofDeasters这与他基本无关,因为他已经远远超过了当天的代表名额。