类属性只能在创建对象时分配
本文关键字:创建对象 分配 属性 | 更新日期: 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; }
}
}