【问题标题】:Type initializer threw an exception类型初始化器抛出异常
【发布时间】:2011-04-16 05:32:53
【问题描述】:

这个类正在抛出异常。它没有显示确切的行号,但听起来它发生在静态构造函数中:

static class _selectors
{
    public static string[] order = new[] { "ID", "NAME", "TAG" };
    public static Dictionary<string, Regex> match = new Dictionary<string, Regex> {
        { "ID", new Regex(@"#((?:[\w\u00c0-\uFFFF-]|\\.)+)") },
        { "CLASS", new Regex(@"\.((?:[\w\u00c0-\uFFFF-]|\\.)+)") },
        { "NAME", new Regex(@"\[name=['""]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['""]*\]") },
        { "ATTR", new Regex(@"\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['""]*)(.*?)\3|)\s*\]") },
        { "TAG", new Regex(@"^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)") },
        { "CHILD", new Regex(@":(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?") },
        { "POS", new Regex(@":(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)") },
        { "PSEUDO", new Regex(@":((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['""]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?") }
    };
    public static Dictionary<string, Action<HashSet<XmlNode>, string>> relative = new Dictionary<string, Action<HashSet<XmlNode>, string>> {
        { "+", (checkSet, part) => {
        }}
    };
    public static Dictionary<string, Regex> leftMatch = new Dictionary<string, Regex>();
    public static Regex origPOS = match["POS"];

    static _selectors()
    {
        foreach (var type in match.Keys)
        {
            _selectors.match[type] = new Regex(match[type].ToString() + @"(?![^\[]*\])(?![^\(]*\))");
            _selectors.leftMatch[type] = new Regex(@"(^(?:.|\r|\n)*?)" + Regex.Replace(match[type].ToString(), @"\\(\d+)", (m) =>
                @"\" + (m.Index + 1)));
        }
    }
}

为什么我不能更改 c'tor 中的这些值?

【问题讨论】:

  • 另外一个建议……请关注design guidelines for .NET。它可能看起来很挑剔,但是驼峰式公共字段,以下划线开头的类......对于任何 .NET 开发人员来说,它看起来就像一团糟,并且会在他们眼中对你产生不良影响。
  • 我很难理解回调和其他东西,你能解释一下代码中以下行的作用:public static Dictionary, string>> relative = new Dictionary, string>> { { "+", (checkSet, part) => { }} };
  • @sc_ray 他有一个字典,该字典具有一个字符串键和一个值,该值是一个 Action,它采用 XmlNode 类型的 HashSet 和一个字符串。他正在使用字典类型初始化程序快捷方式,相当于调用.Add("+", (checkSet, part) =&gt; { });,它将一个新的键值对添加到字典中,其中键为+,值是等效于以下方法的lambda:void EmpyMethod(HashSet&lt;XmlNode&gt; checkSet, string part) { /* nothing */ }
  • @Will:我正在移植一个 JavaScript 库(猜猜是哪一个),并且我正在尝试维护它们的大部分命名约定,所以我不会混淆自己。该类以下划线开头,因为我将其视为成员变量而不是类(它是子类)。整个事情就像一个很大的私有常量。
  • @sc_ray:补充一下将要说的内容……我只是还没有填写那个“匿名方法”。课程大约完成了一半;)还有很多常量要塞进去。我可能会采取不同的方法,因为这有点荒谬。

标签: c# initialization static-classes


【解决方案1】:

如果你查看内部异常,你会看到它声明

集合已修改;枚举 操作可能无法执行。

这意味着您正在更改正在循环的集合,这是不允许的。

宁可将你的构造函数改成类似

static _selectors()
{
    List<string> keys = match.Keys.ToList();
    for (int iKey = 0; iKey < keys.Count; iKey++)
    {
        var type = keys[iKey];
        _selectors.match[type] = new Regex(match[type].ToString() + @"(?![^\[]*\])(?![^\(]*\))");
        _selectors.leftMatch[type] = new Regex(@"(^(?:.|\r|\n)*?)" + Regex.Replace(match[type].ToString(), @"\\(\d+)", (m) =>
            @"\" + (m.Index + 1)));
    }
}

【讨论】:

  • 其实,如果你ToList()它,你可以跳过for,只枚举那个调用的结果。另外,您在这里调用 ToList() 是一个废话,这并不是最好的代码。
  • 是的,确实如此,并且要列出的 废话 可以移到循环之外 X-)
【解决方案2】:

您在枚举集合时正在修改它。你不能那样做。快速解决方法是将键移动到不同的集合中并枚举:

static _selectors()
{
    foreach (var type in match.Keys.ToArray())
    {

另外,如果您检查了内部异常,您会发现情况确实如此。

【讨论】:

  • 内部异常说“集合已修改;枚举操作可能无法执行”。我想这应该是给我的提示,但我一定没有读清楚。
  • @Mark:以后,如果您得到内部异常消息,请将其包含在问题中。我仍然认为您应该将其中的一些逻辑移到类型初始化程序之外:)
  • 这几乎是 jQuery 的直接端口...怪他们怪异的代码 :p 不过字典确实派上用场了,因为我需要使用可变键访问这些正则表达式。
【解决方案3】:

简单的诊断方法:将所有代码移到正常方法中,并找出以这种方式抛出的异常。或者只是在调试器中运行它 - 抛出异常时应该会中断。

我怀疑它会是一个糟糕的正则表达式或类似的东西。

就我个人而言,我认为这在静态构造函数中逻辑过多,但情况略有不同...请注意,您还依赖于此处的初始化顺序:

public static Regex origPOS = match["POS"];

那个目前保证没问题,但是很脆。

【讨论】:

  • 嗯,我确实需要一份match["POS"] 的副本,然后才能在 c'tor 中进行修改……那你建议我在哪里做呢?
  • @Mark:我可能会将大部分工作重构为单独类中的方法。这意味着您可以轻松地对它们进行单元测试。您可以然后从静态构造函数中潜在地使用它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-04-05
  • 1970-01-01
  • 1970-01-01
  • 2021-07-09
  • 1970-01-01
相关资源
最近更新 更多