结构未初始化

时间:2014-08-05 11:33:25

标签: c# types struct static clr

今天,我发现在C#中进行某种枚举可能很有趣,类似于Java中的类枚举(已经多次完成)但是作为不可变的结构。我想出了类似的东西:

public struct TestStruct {

    public static readonly TestStruct Value1 = 1;
    public static readonly TestStruct Value2 = 2;
    public static readonly TestStruct Value3 = 3;

    private int _value;

    private TestStruct(int value) {
        _value = value;
    }

    public static implicit operator int(TestStruct instance) {
        return instance._value;
    }

}

代码编译正确,但是当我尝试访问TestStruct.Value2时,会发生NullReferenceException

这只是一个测试,但现在我想知道...... 静态只读 TestStructs会发生什么?为什么我可以为它们分配一个整数,虽然它们没有被初始化?

更新

这个编译。

public struct LogLevel
{
    // log levels
    public static readonly LogLevel Information = 0x0000;
    public static readonly LogLevel Warning = 0x0001;
    public static readonly LogLevel Error = 0x0002;
    public static readonly LogLevel Verbose = 0x0004;
    public static readonly LogLevel Debug = 0x0008;
    public static readonly LogLevel Trace = 0x0016;
    public static readonly LogLevel Critical = 0x0032;
    public static readonly LogLevel Fatal = 0x0064;


    private static readonly Dictionary<int, LogLevel> Levels
        = new Dictionary<int, LogLevel>();

    private readonly int _value;

    private LogLevel(int value)
    {
        if (Levels.ContainsKey(value))
            throw new ArgumentException("Level already defined.");

        _value = value;
        Levels.Add(value, this);
    }

    public static implicit operator LogLevel(int value)
    {
        LogLevel level;
        if (!Levels.TryGetValue(value, out level))
            throw new ArgumentOutOfRangeException("value");
        return level;
    }

    public static implicit operator int(LogLevel level)
    {
        return level._value;
    }
}

更新2

    // extension method for log levels
    public static void Debug(this ILogger logger, string message)
    {
        logger.Write(message, LogLevel.Debug);
    }

    // method on ILogger, implementation is Log4NetLogger (wrapper)
    void Write(string message, LogLevel severity);

    // call (simple)
    Logger.Debug("Test");

1 个答案:

答案 0 :(得分:2)

这里有两个问题:

  1. 当您初始化字段时,您正在使用int的隐式转化...期望该值已经 。您应该使用构造函数。所以这个:

    public static readonly LogLevel Information = 0x0000;
    

    应该是

    public static readonly LogLevel Information = new LogLevel(0x0000);
    
  2. 您在Levels变量初始化之前尝试访问字典。您需要移动此声明:

    private static readonly Dictionary<int, LogLevel> Levels
        = new Dictionary<int, LogLevel>();
    

    ...在字段声明之上。这样它在字段初始化程序调用构造函数之前就已初始化。

  3. 此时,它应该有效。它不一定是我自己使用的设计,但它至少可以消除你目前所遇到的问题。