Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this producing a Null Value Exception?

Tags:

c#

exception

The exception I get is:

The type initializer for MyNamespace.Program threw an exception

The inner exception says

Message: Value cannot be null. Parameter name: collection
Source: ... HashSet ...

This leads me to believe the error is occuring on the line indicated below...

class Program
{
    public static IEnumerable<char> WordCharacters = ExpandCharacterSet("A-Za-z0-9_");
    public static IEnumerable<char> NonWordCharacters = ExpandCharacterSet("^A-Za-z0-9_");
    public static IEnumerable<char> SpaceCharacters = ExpandCharacterSet(" \f\n\r\t\v");
    public static IEnumerable<char> NonSpaceCharacters = ExpandCharacterSet("^ \f\n\r\t\v");
    public static IEnumerable<char> DigitCharacters = ExpandCharacterSet("0-9");
    public static IEnumerable<char> NonDigitCharacters = ExpandCharacterSet("^0-9");
    public static IEnumerable<char> WildCharacters = ExpandCharacterSet("^\n");
    public static IEnumerable<char> AllCharacters = Enumerable.Range(0, 256).Select(Convert.ToChar).Where(c => !char.IsControl(c));

    public static IEnumerable<char> ExpandCharacterSet(string set)
    {
        if (set.Length == 0)
            return "";

        var sb = new StringBuilder();
        int start = 0;
        bool invertSet = false;

        if (set[0] == '[' && set[set.Length - 1] == ']')
            set = set.Substring(1, set.Length - 2);
        if (set[0] == '^')
        {
            invertSet = true;
            set = set.Substring(1);
        }
        set = Regex.Unescape(set);

        foreach (Match m in Regex.Matches(set, ".-.|."))
        {
            if (m.Value.Length == 1)
                sb.Append(m.Value);
            else
            {
                if (m.Value[0] > m.Value[2]) throw new ArgumentException("Invalid character set.");
                for (char c = m.Value[0]; c <= m.Value[2]; ++c)
                    sb.Append(c);
            }
        }

        if (!invertSet) return sb.ToString();

        var A = new HashSet<char>(AllCharacters); // <---- change this to "ABC" and the error goes away
        var B = new HashSet<char>(sb.ToString());
        A.ExceptWith(B);
        return A;
    }

    static void Main(string[] args)
    {
    }
}

But I don't know why. When I print the chars,

Console.WriteLine(string.Concat(AllChars));

It prints every character as expected. So why does HashSet think it's null?

like image 958
mpen Avatar asked Aug 19 '26 12:08

mpen


1 Answers

I'm guessing that ExpandCharacterSet is being used to initialize another static field. There's no guarantee on the order in which two static fields will be initialized, and so presuably, it's trying to initialize the other field before it initializes AllChars.

Try moving the assignments into an explicit static constructor, with the correct initialization order.

e.g if your current code has:

public static IEnumerable<char> AllChars = Enumerable.Range(0, 256).Select(Convert.ToChar).Where(c => !char.IsControl(c));
public static IEnumerable<char> Expanded = ExpandCharacterSet(...);

Make it instead:

public static IEnumerable<char> AllChars;
public static IEnumerable<char> Expanded;
static <ClassName> {
    AllChars = Enumerable.Range(0, 256).Select(Convert.ToChar).Where(c => !char.IsControl(c));
    Expanded = ExpandCharacterSet(...);
}
like image 161
Damien_The_Unbeliever Avatar answered Aug 21 '26 01:08

Damien_The_Unbeliever



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!