我应该使用字段还是属性

本文关键字:属性 字段 我应该 | 更新日期: 2023-09-27 18:20:37

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

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

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

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

所以这个:

public IEnumerable<string> Products;

在所有方面都与此相同:

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

我应该使用字段还是属性

当一个属性只使用get时,我应该使用字段或属性吗;设置

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

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

这不是真的。

  • 通过反射可以看到差异,这通常非常重要。例如,许多绑定框架不使用字段,只使用属性
  • 您可以通过ref传递可变字段,但不能传递属性,因此将字段更改为属性会破坏源代码的兼容性。(当Products成为属性时,使用SomeMethod(ref x.Products)的代码将无效。)
  • 将字段更改为属性也会破坏二进制兼容性,因此,如果程序集X是根据程序集Y v1.0构建的,并且您将字段更改成程序集Y v1的属性,则需要重新生成程序集X,否则它将无法正确执行
  • 如果您有一个可变的值类型(请不要这样做),那么当Location是字段时(因为x.Location被分类为变量),编写foo.Location.X = 10是有效的,而当Location是属性时(因为表达式x.Location被分类为值),则不起作用。如果你有一个方法(在你的邪恶可变类型中)会改变值,那么foo.Location.DoSomething()在这两种情况下都会编译,但效果不同。全家都很开心

这取决于具体情况。我更愿意使用这处房产而不是田地。您已经提到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;
                }
            }
        }

使用auto-property语法更可取,因为它创建了一个带有专用后台字段的读/写属性,从而允许您更改实现(从专用标量字段更改为字典条目或其他具有其他自定义逻辑的后端),从而从实现中释放"类的接口"(与interface不同)。

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

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

这样只有包含类才能更改它。

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

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