我应该使用田地还是财产?

时间:2015-11-04 08:06:15

标签: c# properties field

首先,我已阅读问题asking for the difference between fields and properties,我知道它的用途。

现在我的问题是,我想创建一个属性,我确信get和set都是空的,所以我做get; set;。一切都很好。但是现在我意识到我刚刚创建了一个带有大写名称的公共领域,它在各方面都是相同的。

即使是使用它的论点,所以未来的代码不依赖于实现也不能说,因为我可以简单地将它作为属性并实现getter或setter。 字段和属性的语义在它定义的类之外是相同的。

所以我的问题是,当一个属性只使用get;set;时,我应该使用字段还是属性?

所以这个:

public IEnumerable<string> Products;

在所有方面都与此相同:

public IEnumerable<string> Products { get; set; }

3 个答案:

答案 0 :(得分:8)

  

当属性只使用get; set;?

时,我应该使用字段还是属性?

使用属性...出于以下实际原因,以及属性公开状态API的哲学原因,而字段公开状态实现细节。

  

字段和属性的语义在它定义的类之外是相同的。

那不是真的。

  • 通过反射可以看出差异,这通常非常重要。例如,许多绑定框架不会使用字段,只能使用属性。
  • 您可以通过ref传递可变字段,但不能传递属性 - 因此将字段更改为属性会破坏源兼容性。 (当SomeMethod(ref x.Products)成为财产时,使用Products的代码将无效。)
  • 将字段更改为属性也会破坏二进制兼容性,因此如果程序集X是针对程序集Y v1.0构建的,并且您将字段更改为程序集Y v1.1的属性,则您需要重建程序集X,否则将无法正确执行
  • 如果你有一个可变值类型(请不要这样做),那么当foo.Location.X = 10是一个字段时,Location可以正常工作(因为x.Location被归类为一个变量)而Location是一个属性时却没有(因为那时表达式x.Location被归类为一个值)。如果你有一个方法(在你的邪恶的可变类型中)改变了值,那么foo.Location.DoSomething()将在两种情况下编译,但具有不同的效果。为所有家庭带来乐趣。

答案 1 :(得分:1)

取决于具体情况。我宁愿在田野上使用这个房产。您已经提到public IEnumerable<string> Products;public IEnumerable<string> Products { get; set; }相同,但实际上并非如此。在编译期间,属性将转换为两个方法(即get_Products()和set_Products())。

属性的优点是允许您在分配和返回数据之前指定自定义代码,这在字段中是不可能的。请查看以下示例

public IEnumerable<string> Products
        {
            get
            {
                if(DateTime.Now.Date > Convert.ToDateTime("01-01-2016"))
                {
                    //Return future product
                    return new List<string>();
                }
                else
                {
                    // return current products
                    return new List<string>() { "testing" };
                }
            }
            set
            {
                if (DateTime.Now.Date > Convert.ToDateTime("01-01-2016"))
                {
                    //ignore assign product
                    Products = new List<string>();
                }
                else
                {
                    // add assign product
                    Products = value;
                }
            }
        }

答案 2 :(得分:0)

使用自动属性语法是首选,因为它创建具有私有支持字段的读/写属性,从而允许您更改实现(从私有标量字段更改为字典条目或其他后端与其他自定义逻辑),从而释放了&#34;类的界面&#34; (与interface)的实现不同。

请注意,对于集合成员属性,建议将其setter设为私有,如下所示:

public IEnumerable<String> Products { get; private set;}

......只有包含类才能改变它。

另一种选择是private readonly字段,在C#6中,您可以使用带有readonly支持字段的自动实现属性,如下所示:

public IEnumerable<String> Products { get; } = SomeSource.GetProducts();