0

I am trying to use a CSV parser which I found on the net in my project. The problem is I am getting a null reference exception when I try to convert the string to a Tag and my collection does not get populated. Can anyone assist? Thanks

CSV Parser

private static IEnumerable<string[]> parseCSV(string path)
    {
        List<string[]> parsedData = new List<string[]>();

        try
        {
            using (StreamReader readFile = new StreamReader(path))
            {
                string line;
                string[] row;

                while ((line = readFile.ReadLine()) != null)
                {
                    row = line.Split(',');
                    parsedData.Add(row);
                }
            }
        }
        catch (Exception e)
        {
            System.Windows.MessageBox.Show(e.Message);
        }

        return parsedData;
    }

Tag Class

  public class Tag
    {
        public Tag(string name, int weight)
        {
            Name = name;
            Weight = weight;
        }

        public string Name { get; set; }
        public int Weight { get; set; }

        public static IEnumerable<Tag> CreateTags(IEnumerable<string> words)
        {
            Dictionary<string, int> tags = new Dictionary<string, int>();

            foreach (string word in words)
            {
                int count = 1;
                if (tags.ContainsKey(word))
                {
                    count = tags[word] + 1;
                }

                tags[word] = count;
            }

            return tags.Select(kvp => new Tag(kvp.Key, kvp.Value));
        }
    }
4
  • Where was the exception thrown? Look at the stack trace. Commented Mar 18, 2011 at 10:22
  • 1
    Look at the stacktrace on the exception and it should pinpoint at exactly what line in your code the exception is thrown. You can also debug your code and when it breaks when the exception is thrown you can discover what variable is null. If you have an exception handler you need to go into the Debug -> Exceptions dialog and mark the Thrown checkbox for the exception to when the exception is thrown. Commented Mar 18, 2011 at 10:22
  • The connection between the 2 code fragments seems to be missing. Commented Mar 18, 2011 at 10:23
  • It breaks on this line: foreach (string word in words) Commented Mar 18, 2011 at 10:38

2 Answers 2

2

Validate all method arguments before you use them!

It breaks on this line: foreach (string word in words)

Remember that foreach loops work by calling GetEnumerator on the collection iterated over. That is, your foreach loop causes a call to words.GetEnumerator, and this call fails if words is null.

Therefore, validate your argument words by adding a guard at the very start of your CreateTags method:

if (words == null)
{
    throw new ArgumentNullException("words");
}

This will help you find the location in your code where null is passed into CreateTags, and you can then continue fixing the calling code.

Suggestion: Avoid null whenever possible.

As a very general rule, try to avoid using null values whenever possible. For example, when your code is dealing with sets and collections of items, you could make sure that it also works correctly with empty collections. In a second step, make sure that you never use null to represent an empty collection; instead, use e.g. LINQ's Enumerable.Empty<TItem>() generator to create an empty collection.

One place where you could start doing this is in the CreateTags method by ensuring that no matter what the inputs are, that method will always return a valid, non-null (but possibly empty) collection:

if (words == null)
{
    return Enumerable.Empty<Tag>();  // You could do without LINQ by writing:
                                     // return new Tag[] { };
}
Sign up to request clarification or add additional context in comments.

4 Comments

See "tags[word] = count;" it adds an entry with key 'word' and value 'count' to tags dictionary. Obviously, your simplification is flawed because it will never populate tags.
Thanks, I think the problem is that I am trying to store the list of arrays generated from my CSV parser code in the words Iennumerable collection how could I fix this?
@Konstantin, what was I thinking! You're absolutely right. Flawed part of my answer removed, thanks for the correction!
@Ben, before you fix anything, you need to find the exact cause. (Adding guard clauses at the methods' beginning that validate arguments will help you there.) I cannot advise you further without more precise information. (The fact that you're storing something in a collection is not per se an error. It's OK to pass a string[] to CreateTags, since string[] is IEnumerable<string>. However, passing the IEnumerable<string[]> from parseCSV into CreateTags obviously won't work and should result in a type error at compile time. You'd need to call CreateTags once per string[].)
0

Every method should run sanity checks on the arguments it accepts to ensure the arguments are valid input parameters. I would probably do something like

public static IEnumerable<Tag> CreateTags(IEnumerable<string> words)
    {
        if(words==null)
        {
           //either throw a new ArgumentException or
           return null; //or return new Dictionary<string,int>();
        }
        Dictionary<string, int> tags = new Dictionary<string, int>();

        foreach (string word in words)
        {
            int count = 1;
            if (tags.ContainsKey(word))
            {
                count = tags[word] + 1;
            }

            tags[word] = count;
        }

        return tags.Select(kvp => new Tag(kvp.Key, kvp.Value));
    }

As to why your "words" param is null, it would be helpful to see the CSV file you are trying to parse in.

Hope this helps!

1 Comment

Thanks, I think the problem is that I am trying to store the list of arrays generated from my CSV parser code in the words Iennumerable collection how could I fix this?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.