我正在使用此处列出的type-safe enum pattern。我需要将一个类型安全的枚举嵌套到另一个中。在创建父构造函数时,子属性(静态对象)为NULL。似乎没有调用子构造函数,并且我得到了一些错误。(父母和孩子我很困惑,但它解释了层次结构)
以下是一个例子(我使用netMF):
public class MyDeviceSetting //parent
{
public readonly string Name;
public MyUnit SettingUnit;
public readonly MyUnit.UnitPurpose UnitPurpose;
#region MY STATIC SETTINGS
//UNIT SETTINGS
public static MyDeviceSetting TempUnits = new MyDeviceSetting("TempUnits", MyUnit.mm); //MyUnit.mm is null. Why?
public static MyDeviceSetting BLAH = new MyDeviceSetting("BLAH", MyUnit.inch);//MyUnit.inch is null. Why?
#endregion
/// <summary>
/// This is the MAIN PRIVATE Constructor
/// </summary>
/// <param name="?"></param>
private MyDeviceSetting(string name, MyUnit defaultUnit)
{
Name = name;
SettingUnit = defaultUnit;//NULL
UnitPurpose = SettingUnit.Purpose; //fails because SettingUnit is NULL
}
}
public sealed class MyUnit
{
private static int Count = 0;
//these are used to store and identify the unit in memory
public readonly int UnitID;
public readonly int TestID;
public enum UnitPurpose
{
DISTANCE,
SPEED,
TEMPERATURE,
TIME,
CLOCK,
NO_UNITS
}
public readonly string DisplayName;
public readonly string Abbreviation;
public readonly string Name;
public readonly UnitPurpose Purpose;
#region My Units
public static readonly MyUnit mm = new MyUnit("Milimeters", "mm", "mm", UnitPurpose.DISTANCE, 1);
public static readonly MyUnit inch = new MyUnit("inch", "inch", "in", UnitPurpose.DISTANCE, 2);
#endregion
private MyUnit(string name,
string displayName,
string abbreviation,
UnitPurpose unitPurpose,
int unitID)
{
Name = name;
DisplayName = displayName;
Abbreviation = abbreviation;
Purpose = unitPurpose;
UnitID = unitID;
TestID = Count;
Count++;
}
}
如何确保child
不为空?有解决方法吗?编辑:This Post确保此功能正常运行,但就我而言,它无效。
答案 0 :(得分:1)
这似乎是.Net Micro框架的错误/限制。它不完全支持静态构造函数。以下是报告相同问题的人:https://msdn.microsoft.com/en-us/library/Cc533032.aspx
NetCF 3.0的documentation包含以下警告:
不要使用静态构造函数。 .NET Micro Framework尚未完全支持它们。
从这个blog post似乎也说(至少从2.0开始)对静态构造函数的调用被序列化了:
在.NET Compact Framework中有一些无法完成的事情 完整.NET Framework中可能的静态构造函数。 基本上,所有静态构造函数都是在序列化中执行的 .NET Compact Framework V2中的时尚
那篇文章在死锁的背景下讨论它,但我相信这是不起作用的原因。
不幸的是,这意味着你不能依赖静态,并且必须自己处理初始化和锁定。这样的事情应该有效:
private static MyUnit inch;
public static MyUnit Inch
{
get
{
if (inch == null)
inch = new MyUnit("inch", "inch", "in", UnitPurpose.DISTANCE, 2);
return inch;
}
}
遗憾的是,它失去了静态构造函数给你的线程安全性。这很难解决,因为你不能依赖静态成员,因为我们已经看到你不能依赖它们被初始化。
答案 1 :(得分:1)
作为一种解决方法,您可以将offset = rand(Quote.count)
rand_record = Quote.offset(offset).first
类移动到另一个名为MyUnit.cs的源文件,这将导致.netmf CLR首先加载此类。
答案 2 :(得分:0)
看起来你的问题很难复制,任何方式都需要务实。
您可以在MyUnit
静态字段首先调用MyDeviceSetting
之前初始化MyUnit
个静态字段。
这很简单,只需在程序中的任何其他内容之前创建一个虚拟变量。
public class MyDeviceSetting //parent
{
static MyDeviceSetting()
{
var dummy = MyUnit.inch;
}
}
因此,永远不会使用虚拟var,但会初始化MyUnit的静态实例。
之后,MyDeviceSetting
的所有活动都会初始化MyUnit
。
答案 3 :(得分:0)
除了@ shf301以及为什么它不能正常工作的原因之外,似乎在编译时以某种类型的字母/字母数字顺序调用构造函数。
将子类重命名为MyAUnit
使其在MyDeviceSetting
之前出现,并且似乎在MyAUnit
静态成员之前触发MyDeviceSetting
个静态成员。
这似乎有效,但暂时还有点“黑客”。