何时应使用只读 (Readonly) 和只取 (Get only) 属性?

120

在.NET应用程序中,何时应该使用“只读”属性,何时应该只使用“Get”。这两者之间有什么区别。

private readonly double Fuel= 0;

public double FuelConsumption
{
    get
    {
        return Fuel;
    }
}        
或者
private double Fuel= 0;

public double FuelConsumption
{
     get
     {
          return Fuel;
     }
}

16
对于 C# 版本大于 5,get 属性可以简写为 public double FuelConsumption => Fuel; - meJustAndrew
5个回答

144

创建仅具有getter的属性可以使该属性只读,对于任何位于类外部的代码都是如此。

但是您可以使用类提供的方法更改值:

public class FuelConsumption {
    private double fuel;
    public double Fuel
    {
        get { return this.fuel; }
    }
    public void FillFuelTank(double amount)
    {
        this.fuel += amount;
    }
}

public static void Main()
{
    FuelConsumption f = new FuelConsumption();

    double a;
    a = f.Fuel; // Will work
    f.Fuel = a; // Does not compile

    f.FillFuelTank(10); // Value is changed from the method's code
}

将类的私有字段设置为readonly,只允许在类的构造函数中设置该字段值(使用内联赋值或已定义的构造函数方法)。 稍后将无法更改它。

public class ReadOnlyFields {
    private readonly double a = 2.0;
    private readonly double b;

    public ReadOnlyFields()
    {
        this.b = 4.0;
    }
}

readonly 类字段常用于在类构造期间初始化的变量,以后永远不会更改。

简而言之,如果你需要确保属性值从外部永远不会被改变,但是你需要能够从内部类代码中更改它,使用“只读取”属性。

如果您需要存储一个一旦设置了初始值就永远不会更改的值,请使用 readonly 字段。


19
+1 个代码示例。但需要明确指出,“只读”属性仅在它们被包装在类字段上的类方法中才能被修改。如果没有 setter,即使是类方法也无法直接修改它们,尝试这样做将导致编译器错误。 - Devraj Gadhavi
1
除了构造函数之外,使用public double Fuel { get; } = 42;,以下代码可以编译通过:public FuelConsumption() { Fuel +=10; } - Agent49
1
只读变量可以在构造函数中分配多次,因此您的最后一句话是不正确的。 - duesterdust
1
@duesterdust 感谢您的评论,我编辑了我的答案以使其更清晰。 - Thibault Falise

22

截至2015年的C# 6版,你可以在一行代码中声明和初始化一个只读自动属性

double FuelConsumption { get; } = 2;

你可以从构造函数中设置值,但不能在其他方法中设置。


那是一个字段,对吧?只读自动属性使用=> - undefined

8

如果一个属性只有getter方法,那么它被称为只读属性。因为没有提供setter方法,所以无法从外部更改属性的值。

C#语言中有一个关键字readonly,可以用于字段(而不是属性)。标记为“readonly”的字段只能在对象构造期间(在构造函数中)设置一次。

private string _name = "Foo"; // field for property Name;
private bool _enabled = false; // field for property Enabled;

public string Name{ // This is a readonly property.
  get {
    return _name;  
  }
}

public bool Enabled{ // This is a read- and writeable property.
  get{
    return _enabled;
  }
  set{
    _enabled = value;
  }
} 

2

只读属性用于创建防错代码。

我非常喜欢Mark Seemann关于属性和支撑字段的封装系列文章:Poka-yoke Design:从气味到香味

取自Mark的示例:

public class Fragrance : IFragrance
{
    private readonly string name;
 
    public Fragrance(string name)
    {
        if (name == null)
        {
            throw new ArgumentNullException("name");
        }
 
        this.name = name;
    }
 
    public string Spread()
    {
        return this.name;
    }
}

在这个例子中,你使用只读的名称字段来确保类不变式始终有效。在这种情况下,类作曲家希望确保名称字段仅设置一次(不可变)且始终存在。

-1

方法(Methods)意味着需要执行某些操作才能返回值,而属性(Properties)则意味着该值已经存在。这是一个经验法则,有时您可能希望属性执行一些工作(例如Count),但通常这是一种有用的决策方式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接