How does a IList.Distinct method throws ArgumentNullException in the given scenario

时间:2017-06-19 13:54:44

标签: c# linq

I am facing a very weird issues and not sure where the problem is. When I walk through the code and analyze all the scenario, I do not see that in any case it can through ArgumentNullException.

But somehow in production server, it throws the following exception:

Exception details: System.ArgumentNullException: Value cannot be null. Parameter name: source
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at GetDistinctValues(IList`1 textNames)

I have extracted the code in a sample console application. Can anyone tell me the possible scenarios when GetDistinctValues method can throw this ArgumentNullException?

Sample code snippet:

private IList<string> GetDistinctValues(IList<string> textNames)
{
    var values = GetTextValues(textNames);
    var trimmedValues = values.Select(value => value.Trim());
    return trimmedValues.Distinct(StringComparer.InvariantCultureIgnoreCase).ToList();
}

public static IList<string> GetTextValues(IList<string> textNames)
{
    var values = new List<string>();
    var names = (List<string>)textNames;
    if (!names.Any())
    {
        return null;
    }

    names.ForEach(x => values.Add(GetValue(x)));

    return values;
}

private static string GetValue(string name)
{
    // returns some value depending on name

    return "someValue";
}

2 个答案:

答案 0 :(得分:0)

ToList是一种扩展方法,可能带有如下签名:public static List<T> ToList<T>(this IEnumerable<T> source)。在阅读异常时,source为空。因此,GetTextValues返回null。当没有names时它会这样做。

答案 1 :(得分:0)

如果你想在LINQ中使用你的收藏,你应该这样做 从来没有!永远!如果你没有任何回报,则返回null。相反,您应该返回Enumerable.Empty或空集合。如果你的函数决定它没有要返回的元素,它应该返回一个枚举器,在这种情况下枚举器没有枚举元素。

考虑更改你的功能:

public static IEnumerable<string> GetTextValues(IEnumerable<string> textNames)
{
    if (textNames == null)
        return Enumerable.Empty<string>();
        // or consider: throw ArgumentNullException(nameof(textNames));
    return textNames.Select(textName => GetValue(textName));
}

返回枚举而不是List的好处是,如果函数的用户只需要列表的前几个元素,则只创建少量元素。