是否有一种方法可以在不使用构造函数的情况下初始化结构的成员
本文关键字:构造函数 情况下 成员 结构 初始化 方法 一种 是否 | 更新日期: 2023-09-27 18:15:07
我有一个包含两个列表的struct
:
struct MonthData
{
public List<DataRow> Frontline;
public List<DataRow> Leadership;
}
但是,我希望在创建结构体时对两者进行初始化。如果我尝试:
struct MonthData
{
public List<DataRow> Frontline = new List<DataRow>();
public List<DataRow> Leadership = new List<DataRow>();
}
得到:
Error 23 'MonthData.Frontline': cannot have instance field initializers in structs
...
因为结构不能有无参数的构造函数,所以我也不能在构造函数中设置它。到目前为止,我只能看到以下选项:
- 在创建MonthData 实例时初始化这两个属性
- 用类代替struct
- 创建一个带参数的构造函数并使用
- 为初始化它们的属性创建getter和setter懒洋洋地。
推荐的方法是什么?现在,我认为把它作为一个类是最好的主意。
您应该使用类来代替。从MSDN:
一般来说,类用于为更复杂的行为建模,或者在创建类对象后要修改的数据。
无论如何,您在结构体中使用引用类型(List<T>
),因此使用结构体作为值类型对我来说没有任何意义。
如果你只是在问语法…尝试构建和使用静态工厂来代替…一般来说,结构应该用于不可变的对象,而对于不可变类型,工厂(调用私有构造函数)是比使用公共构造函数更好的方法。
struct MonthData
{
public List<DataRow> Frontline;
public List<DataRow> Leadership;
private MonthData(List<DataRow> frontLine = null,
List<DataRow> leadership = null)
{
Frontline = frontLine?? new List<DataRow>();
Leadership = leadership?? new List<DataRow>();
}
public static MonthData Factory(
List<DataRow> frontLine= null,
List<DataRow> leadership= null)
{ return new MonthData(frontLine, leadership); }
}
在构造函数中无法做到这一点。CLR可以并且将创建结构体的实例,只需初始化内存为零,并避免任何actor开销。然而,你可以利用这些知识来创建延迟初始化的属性,这些属性具有相同的可观察效果。
例如:struct MonthData {
private bool m_initialized;
private List<DataRow> m_frontLine;
private List<DataRow> m_leaderShip;
public List<DataRow> FrontLine {
get {
EnsureInitialized();
return m_frontLine;
}
}
public List<DataRow> LeaderShip {
get {
EnsureInitialized();
return m_leaderShip;
}
}
void EnsureInitialized() {
if (!m_initialized) {
m_initialized = true;
m_frontLine = new List<DataRow>();
m_leaderShip = new List<DataRow>();
}
}
}
如果CLR允许一种方法来保证结构类型的东西可以在它们对这些代码之外的任何东西可见之前运行一些初始化代码,那将是很好的。即使在创建结构类型的数组时,也可以这样做,方法是让CLR在任何地方公开对数组本身的引用之前通过引用传递数组的所有单个元素。不幸的是,如果在创建数组期间抛出异常,就会导致一种尴尬的情况。如果构造函数没有任何副作用,就不会有问题——只需丢弃数组并假装即使成功创建的对象也不存在。然而,有副作用的构造函数可能会造成一些困难。
然而,事实上,没有办法在构造时初始化结构,因此没有很好的方法来实现需要初始化的对象的值类型语义。对不起。即使值类型语义更适合您的类型(这种情况比有些人认为的要频繁得多),如果需要初始化,您也必须使用引用类型。结构体的延迟初始化实际上不起作用。例如,如果有一个Dictionary<String,>称为MyDict,重复访问MyDict("George")。FrontLine将分别生成一个新的List。讨厌。可变结构不是邪恶的;如果说有什么不同的话,那就是我是他们最坚定的支持者之一。尽管如此,.net对可变结构的处理有一些限制,因此在许多情况下值类型语义是合适的,但是。net的限制使它不可能正确地提供这种语义。