Question

This class is throwing an exception. It doesn't show me the exact line number, but it sounds like it's occurring in the static constructor:

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

Why can't I change those values in the c'tor?

Was it helpful?

Solution

You're modifying a collection while enumerating it. You can't do that. Quick fix is to move the keys into a different collection and enumerate that:

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

Also, if you had checked the inner exception you would have seen that was the case.

OTHER TIPS

If you view the inner exception, you will see that it states

Collection was modified; enumeration operation may not execute.

This means you are changing the collection you are looping, which is not allowed.

Rather change your constructor to something like

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

Simple diagnostic approach: Move all that code into normal methods, and find out what exception is being thrown that way. Or just run it in the debugger - that should break when the exception is thrown.

I suspect it'll be a bad regular expression or something like that.

Personally, I think this is too much logic in a static constructor, but that's a slightly different matter... Note that you're also relying on the ordering of the initialization here:

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

That is guaranteed to be okay at the moment, but it's very brittle.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top