2017-01-22 50 views
2

我想从列表中创建一个字典,所以我会用这样的方式:字典将空键

Dictionary<long, List<MyType>> miDicIdMyType = myList.GroupBy(x => x.ForeignKey) 
               .ToDictionary(x => x.Key, x => x.ToList()); 

的问题是,有时该属性可以为空,这样我就可以创建字典,因为字典不允许空值作为键。

但在这种特殊情况下,我必须检查该属性是否为null,如果它为null,则抛出异常,因为这是一个错误。在这个特定的方法中,我希望列表中的所有项目在此属性中都不为空。

所以,我可以这样做:

Dictionary<long, List<MyType>> miDicIdMyType = myList.GroupBy(x => (long)x.ForeignKey) 
             .ToDictionary(x => x.Key, x => x.ToList()); 

这是一个强制转换为长,但如果是空的,我会得到一个错误。所以基本上我想这样做:

Dictionary<long, MyType> myDic = new Dictionary<long, myType>(); 
foreach (Mytype iterator in miList) 
{ 
    if (iterator.ForeignKey == null) 
    { 
     throw new ArgumentNullException("Some items in the collection has null value and it is not expected."); 
    } 

    if (myDic.ContainsKey(iterator.ForeignKey) == false) 
    { 
     myDic.Add(iterator.ForeignKey, new List<MyType>()); 
    } 

    myDic[iterator.ForeignKey].Add(iterator); 
} 

我想知道这是否是一个好的代码或我可以做一个更好的方式,与LINQ或lambda表达式或任何其他方式。我的意思是,简化我的代码。

+0

你可以重构'X => x.ForeignKey'到一个多拉姆达expession'Func键'和的情况下,抛出一个异常'T.ForeignKey'是* NULL *。 – user3185569

+0

另一种选择是'Dictionary >'。 –

回答

3

您正在寻找类似的东西?

Dictionary<long, List<MyType>> miDicIdMyType = myList.GroupBy(x => 
{ 
    if (x.ForeignKey == null) 
     throw new Exception(); 
    return x.ForeignKey.Value; 
}) 
.ToDictionary(x => x.Key, x => x.ToList()); 
+0

谢谢,是的,我一直在思考类似的问题,但是我不太了解这类语法。 –

2

首先,您正在创建查找。只需执行以下操作:

var lookup = data.ToLookup(x => x.ForeignKey); 

如果您需要对密钥进行额外的检查,则命名方法会为可重用性和可读性创造奇迹。

T IsNotNull<T>(T? obj, [CallerMemberName] string name = default(string)) where T : struct 
{ 
    if (obj == null) 
     throw new ArgumentNullException(name); 
    return obj.Value; 
} 

var lookup = data.ToLookup(x => IsNotNull(x.ForeignKey)); 

但是,即使使用它,我也会提醒你。你的linq查询不应该依赖/引起副作用,尤其是对于懒惰的评估。您应该不惜一切代价阻止这些特殊情况,而不是寻找提高它们的理由。在这个特殊情况下,在这个代码中的例外是不合适的。这是一个简单的数据问题,应该被滤除。

你为什么不把它们过滤出来呢?

var lookup = data.Where(x => x.ForeignKey != null).ToLookup(x => x.ForeignKey.Value); 
+0

我想在第一时间过滤像你一样,但我想这需要迭代两次集合,一个用于过滤和其他创建字典/查找。 无论如何,我想抛出一个异常,因为我认为足够重要的这种情况下,不只是过滤和继续。 –

+1

通常,在使用LINQ时,原始源集合在整个查询中遍历_once_。这些值仅在每个过滤器中传递。 –

+0

我可以从哪里获得更多关于这方面的信息,或者我该如何测试?谢谢。 –