2011-03-18 78 views
0

我想在我的项目中使用我在网上找到的CSV解析器。问题是当我尝试将字符串转换为标记并且我的集合没有被填充时,我得到空引用异常。任何人都可以协助由于C#NullReferenceException未处理

CSV分析器

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

标记类

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

抛出异常在哪里?看看堆栈跟踪。 – 2011-03-18 10:22:48

+1

查看有关异常的堆栈跟踪,它应该精确地指出代码中的哪一行引发了异常。你也可以调试你的代码,当它抛出异常时它会中断,你可以发现什么变量是null。如果你有一个异常处理程序,你需要进入Debug-> Exceptions对话框,并且标记Thrown复选框以查找抛出异常的异常。 – 2011-03-18 10:22:49

+0

2个代码片段之间的连接似乎缺失。 – 2011-03-18 10:23:44

回答

2

验证所有方法参数后再使用它们!

它打破了在这条线:的foreach(串词的话)

记住foreach循环调用GetEnumerator在集合遍历工作。也就是说,您的foreach循环导致对words.GetEnumerator的呼叫,并且如果words为空,则此呼叫失败。

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

这将帮助您寻找到null传递到CreateTags在你的代码的位置,您可以:

因此,在你CreateTags方法最开始的附加保护验证你的论点words然后继续修复调用代码。

建议:尽可能避免null

作为一个非常普遍的规则,尽可能避免使用null值。例如,当您的代码处理项目的集合和集合时,可以确保它对空集合也能正确工作。在第二步中,确保您从不使用null来表示一个空集合;相反,使用例如LINQ的Enumerable.Empty<TItem>()生成器创建一个空集合。

一个地方,你可以开始通过确保不管输入是什么,该方法将总是返回一个有效的,非空(但可能为空)收集这样做是在CreateTags方法:

if (words == null) 
{ 
    return Enumerable.Empty<Tag>(); // You could do without LINQ by writing: 
            // return new Tag[] { }; 
} 
+0

请参阅“tags [word] = count;”它为标签字典添加了一个带有“单词”和值“计数”的条目。显然,你的简化是有缺陷的,因为它永远不会填充标签。 – 2011-03-18 12:39:20

+0

谢谢,我认为问题是我试图将我的CSV解析器代码生成的数组列表存储在单词Iennumerable集合中,我该如何解决这个问题? – Ben 2011-03-18 13:06:39

+0

* @康斯坦丁*,我在想什么!你是绝对正确的。我的答案有缺陷的部分被删除,谢谢你的更正! – stakx 2011-03-18 17:08:59

0

每个方法都应该接受它,以确保参数是有效的输入参数的参数运行的完整性检查。我可能会不喜欢

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

东西至于为什么你的“话”参数为空,这将是有益的,看看的CSV文件试图解析英寸

希望这有助于!

+0

谢谢,我认为问题是我试图将我的CSV解析器代码生成的数组列表存储在单词Iennumerable集合中,我该如何解决这个问题? – Ben 2011-03-18 13:05:29

相关问题