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

时间:2011-04-18 19:35:34

标签: c#

在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”。

9 个答案:

答案 0 :(得分:7)

我将通过使用私有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; }
}

答案 1 :(得分:3)

这是因为你正在使用的代码:

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");

这意味着您将无法再使用语法糖(对象初始值设定项,我认为它被调用)来实例化该类,您必须使用构造函数。因此,这将是当前实现的一个重大变化,但却是产生所需功能的简单方法。

答案 2 :(得分:2)

如果您倾向于使用初始化程序语法,那么执行此操作的典型方法是创建“popsicle”对象,可以开始流畅的对象,但随后冻结它们并锁定更改。

基本上,我会创建这样的类(使用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;
        }
    }
}

答案 3 :(得分:1)

嗯,有点可能:)

make set private并创建公共构造函数,以便您可以传递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
    }
}

答案 4 :(得分:1)

假设您只是通过构造函数设置值,您可以显式编写set方法以检查它分配的字段是否为未分配(null或其他),如果未分配,则仅写入集合中的值。这样你的设置就可以有效地写入一次。它会在那里大部分时间。

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;
        }
      }


}

答案 5 :(得分:1)

一个标准解决方案是在构造函数中接受属性的初始值 - 如下所示:

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

答案 6 :(得分:0)

添加构造函数并使它们成为返回变量的属性:

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; }
    }
}

答案 7 :(得分:0)

然后我相信你想使用构造函数而不是初始化。

如果你的班级是

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; }
      }

然后使用友好类初始化值(根据您的原始代码)和公共属性来读取值。

答案 8 :(得分:0)

如果你想拥有漂亮的语法,那么你可以使用你的constuctor的默认值

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");