类属性只能在创建对象时分配

本文关键字:创建对象 分配 属性 | 更新日期: 2023-09-27 17:50:24

在c#中可以这样写:

Instrument instr = new Instrument { ClassCode = "Hello", Ticker = "World" };

然而,要做到这一点,你必须在相应的类中添加set;:

class Instrument
{
    public string ClassCode { get; set; }
    public string Ticker { get; set; }
}

这意味着以后有人可能会不小心改变值:

instr.ClassCode.set = "Destroy"

我不允许那样。也就是说,一方面我想要一个只读属性,另一方面我想创建这样的对象:

Instrument instr = new Instrument { ClassCode = "Hello", Ticker = "World" };

我不确定这是否可能。也许我应该用字段或者别的东西,而不是属性。我只想保留最后一句的语法,但同时保持只读。

upd:简而言之,无论如何都不允许使用只读属性。在这种情况下应该使用常规构造函数和"get"。

类属性只能在创建对象时分配

我将通过使用私有setter并从构造函数调用它们来实现这一点。这样你就可以控制何时调用setter。

Instrument instr = new Instrument("Hello", "World");
class Instrument
{
    public Instrument(string ClassCode, string Ticker) 
    {
        this.ClassCode = ClassCode;
        this.Ticker = Ticker;
    }
    public string ClassCode { get; private set; }
    public string Ticker { get; private set; }
}

这是因为您使用的代码:

Instrument instr = new Instrument { ClassCode = "Hello", Ticker = "World" };

只是语法糖:

Instrument instr = new Instrument();
instr.ClassCode = "Hello";
instr.Ticker = "World";

上面的两个示例完全相同,前者只是后者的简写。

你想要实现这个功能的是使这些值私有。像这样:

class Instrument
{
  private string _classCode;
  private string _ticker;
  public string ClassCode{ get { return _classCode; } }
  public string Ticker{ get { return _ticker; } }
  private ClassCode() {}
  public ClassCode(string classCode, string ticker)
  {
    _classCode = classCode;
    _ticker = ticker;
  }
}

这里有:

  • 私有值,这些值只能在类中设置,因此它们不能被其他人稍后覆盖。
  • 公共只读属性,用于读取这些值。
  • 一个私有的默认构造函数,这样没有人可以实例化这个对象而不提供必要的值。
  • 一个需要必要值的公共构造函数。

你可以这样实例化它:

Instrument instr = new Instrument("Hello", "World");

这意味着您将不能再使用语法糖(对象初始化器,我认为它被称为)来实例化类,您必须使用构造函数。因此,对于当前的实现来说,这将是一个突破性的变化,但却是一种生成所需功能的简单方法。

如果你倾向于初始化语法,一种典型的方法是创建"冰棒"对象,这些对象一开始可以是流动的,但随后你冻结它们,并锁定更改。

基本上,我将像这样创建类(用LINQPad测试):
void Main()
{
    Instrument instr1 = new Instrument
    {
        ClassCode = "Hello",
        Ticker = "World"
    };
    instr1.ClassCode = "123";              // is allowed
    Instrument instr2 = new Instrument
    {
        ClassCode = "Hello",
        Ticker = "World"
    }.Freeze();                            // <-- notice Freeze here
    instr2.ClassCode = "123";              // throws InvalidOperationException
}
public class Instrument
{
    private string _ClassCode;
    private string _Ticker;
    private bool _IsFrozen;
    public string ClassCode
    {
        get { return _ClassCode; }
        set
        {
            ThrowIfFrozen();
            _ClassCode = value;
        }
    }
    public string Ticker
    {
        get { return _Ticker; }
        set
        {
            ThrowIfFrozen();
            _Ticker = value;
        }
    }
    private void ThrowIfFrozen()
    {
        if (_IsFrozen)
            throw new InvalidOperationException(
                "Instrument object has been frozen");
    }
    public Instrument Freeze()
    {
        _IsFrozen = true;
        return this;
    }
    public bool IsFrozen
    {
        get
        {
            return _IsFrozen;
        }
    }
}

假设您只通过构造函数设置值,您可以显式地编写set方法来检查它分配给的字段是否未分配(null或其他),并且仅在未分配时才将值写入set中。这样,您的集合有效地只写一次。它会到达那里的大部分地方。

class Instrument
{
     private string _classCode;
     private string _ticker;
     public string ClassCode
     {
        get
        {
          return _classCode;
         }
        set
        {
           if (_classCode == null)
              _classCode = value;
        }
      }
     public string Ticker     {
        get
        {
          return _ticker;
         }
        set
        {
           if (_ticker == null)
              _ticker = value;
        }
      }

}

一个标准的解决方案是在构造函数中接受属性的初始值——就像这样:

class Instrument
{
  public string ClassCode {get; private set}
  public Instrument (string classCode)
  {
    this.ClassCode = classCode;
  }
}

嗯,有点可能:)

设置私有并创建公共构造函数,这样你就可以传递ClassCode和Ticker,即:

class Instrument
{
    public string ClassCode { get; private set; }
    public string Ticker { get; private set; }
    public Instrument(ClassCode classCode, Ticker ticker)
    {
         ClassCode = classCode;
         Ticker = ticker
    }
}

如果你想有一个好的语法,那么你可以使用默认值为你的构造函数

class Instrument {
    public Instrument(string ClassCode = null, string Ticker = null)
    {
        this.ClassCode = ClassCode;
        this.Ticker = Ticker;
    }
    public string ClassCode { get; private set; } 
    public string Ticker { get; private set; } 
}

,那么你可以在代码中创建这样的对象:

Instrument instrument = new Instrument(ClassCode: "classCode", Ticker: "ticker");

那么我相信您想使用构造函数而不是初始化。

如果你的class是
class Instrument
{
    private string _ClassCode;
    private string _Ticker;
    public Instrument(string ClassCode, string Ticker)
{
_ClassCode = ClassCode;
_Ticker = Ticker;
}
    public string ClassCode { get {return _ClassCode;}}
    public string Ticker { get {return _Ticker;} }
}

你会得到想要的效果。

您可以创建不同访问级别的单独属性,例如:

private string _ClassCode;
      internal string ClassCodeSet
      {
         set { _ClassCode = value; }
      }
      public string ClassCode
      {
         get { return _ClassCode; }
      }

然后使用一个友好的类来初始化值(根据原始代码),并使用公共属性来读取该值。

添加一个构造函数并使其成为返回变量的属性:

class Instrument
{
    private string classCode;
    private string ticker;
    Instrument(string classCode, string ticker)
    {
        this.classCode = classCode;
        this.ticker = ticker;
    }
    public string ClassCode
    {
         get { return classCode; }
    }
    public string Ticker
    {
          get { return ticker; }
    }
}