5

在这个例子中 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();
    }
}

AFAIK 他们的行为完全相同。如果他们这样做,为什么不使用 Foo 中的普通字段?在 java 中,我们使用 setter 来强制执行新的不变量而不破坏代码和 getter 以返回安全数据,但在 c# 中,您始终可以将 Foo 重写为:

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

旧代码不会被破坏。

4

5 回答 5

11

AFAIK 他们的行为完全相同。

不,他们没有。

  • 字段不能用于数据绑定(至少在某些绑定实现中)
  • 您可以稍后为属性添加更多逻辑,而不会破坏源代码或二进制兼容性
  • 属性不能通过引用传递
  • 您不能将初始化程序添加到自动实现的属性
  • 它们在反射方面显然会有所不同
  • 从哲学上讲,属性在逻辑上是 API 的一部分,而字段是实现细节

在 c# 中,您始终可以将 Foo 重写为:[...]

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

有关更多咆哮,请参阅我关于此的文章

于 2013-03-21T15:01:31.773 回答
1

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

您可以像访问字段一样访问属性,但在访问属性时会在内部调用 set/get 方法。

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

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

于 2013-03-21T15:00:04.693 回答
0

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

于 2013-03-21T15:00:03.273 回答
0

1)您可以添加私有访问器来获取或设置和控制对属性的访问。

public object MyProp {get; private set;}

你可以在任何地方阅读道具,但只能在课堂上写

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

3)你不能序列化字段

于 2013-03-21T15:01:49.870 回答
0

public string Something{get; set;}只是语法糖;编译器实际上将其扩展为方法。因此get; set;,仅仅为了它而将所有字段都放在一个地方没有什么意义。

于 2013-03-21T15:01:58.923 回答