【问题标题】:Structs not being initialized结构未初始化
【发布时间】:2014-08-05 11:33:24
【问题描述】:

今天,我发现在 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

这只是一个测试,但现在我想知道.. static readonly 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");

【问题讨论】:

  • 这将是一个有趣的问题,如果它编译 - 但它没有。请给出一个简短但完整的程序来说明问题。
  • 代码编译好了吗?你确定吗?我们不能。我的猜测是你有一个class 而不是struct,这也无法编译..
  • 检查这个小提琴:dotnetfiddle.net/CL9pLF。如果你有一个 implicit operator TestStruct(int instance) 它会编译。但仍然没有NullReferenceException
  • @PatrickHofman 是的,你是对的。忘记复制那个了。做了一个可以编译的新例子。
  • 所以它编译...但你没有给任何东西 using 它...(再次:认为 shortcomplete 示例。)

标签: c# types struct static clr


【解决方案1】:

这里有两个问题:

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

    ... 在字段声明之上。这样它在字段初始化器调用构造函数之前就被初始化了。

到那时,它应该可以工作。这不一定是我自己会使用的设计,但它至少可以解决您目前遇到的问题。

【讨论】:

  • 你睡觉吗?好的,您的建议解决了我的问题。 “这不一定是我自己会使用的设计”——为什么?这只是一个测试,永远不会投入生产,但我想知道它有什么“错误”。背后发生了什么,有什么主要的缺点吗?
  • @xvdiff:我不确定你所说的“后面发生了什么”是什么意思,但我觉得它不是很地道。我通常只使用枚举来代替 - 这确实意味着您需要验证它,但这是表示一组命名整数值的惯用方式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-16
  • 1970-01-01
相关资源
最近更新 更多