繁体   English   中英

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

[英]Should I use a field or a property?

首先,我已经阅读了询问字段和属性之间差异的问题,我知道它的用途。

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

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

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

所以这:

public IEnumerable<string> Products;

在各方面都是相同的:

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

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

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

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

这不是真的。

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

这取决于具体情况。 我宁愿在场上使用该物业。 您已经提到过public IEnumerable<string> Products; public IEnumerable<string> Products { get; set; } public IEnumerable<string> Products { get; set; } 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;
                }
            }
        }

使用自动属性语法是首选,因为它创建具有私有后备字段的读/写属性,从而允许您更改实现(从私有标量字段到字典条目或其他后端与其他自定义逻辑),因此从其实现中释放“类的接口”(与interface )。

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

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

...那样只有包含类可以改变它。

另一个替代方案是private readonly字段,在C#6中,您可以使用自动实现的属性和readonly备用字段,如下所示:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM