我有一些失败的代码 - 实际上我无法编辑它。在这之后,我试图找出这段代码的操作,即这是做什么的。它失败了,但我不知道到底在哪里。
Dictionary<long, IList<Cell>> ByBlock =
mCache.ListBlocks.SelectMany(e => e.Value).Where(e => listBlocks.Contains(e.Key)).Select(
Block => new KeyValuePair<long, IList<CellToSubCatchment>>(Block.Key,
DataMgr.GetMapping(
"CASH",
Block,
GetKey(IdKeys, Block),
mType))).ToDictionary(e => e.Key, e => e.Value);
我收到错误:Value cannot be null
,但我不知道什么值为null,因为我无法编辑代码或在即时窗口中运行Lambda,所以我在调试时遇到问题。那么关于它是如何工作的任何想法或更好的方式来看待这些lambdas?
答案 0 :(得分:3)
由于字典具有键和值,因此有点误导,但在尝试将null
键插入Dictionary
时,您会收到该错误(您是允许在字典中包含null
个值。
我认为您可以在查询中早些时候过滤掉null
值,这样您以后就不会以null
键结束。我为&& e.Key != null
添加了一个条件。
Dictionary<long, IList<Cell>> ByBlock =
mCache.ListBlocks.SelectMany(e => e.Value)
.Where(e => listBlocks.Contains(e.Key)
&& e.Key != null) // filter out `null` values
.Select(Block =>
new KeyValuePair<long, IList<CellToSubCatchment>>(
Block.Key,
DataMgr.GetMapping("CASH", Block,
GetKey(IdKeys, Block),
mType)))
.ToDictionary(e => e.Key, e => e.Value);
答案 1 :(得分:2)
将代码重新格式化,如下所示:
Dictionary<long, IList<Cell>> ByBlock =
mCache.ListBlocks
.SelectMany(e => e.Value)
.Where(e => listBlocks.Contains(e.Key))
.Select(Block => new KeyValuePair<long, IList<CellToSubCatchment>>(
Block.Key,
DataMgr.GetMapping("CASH",Block,GetKey(IdKeys, Block), mType))
)
.ToDictionary(e => e.Key, e => e.Value);
我最好的选择是ListBlocks.SelectMany(e => e.Value)
调用失败,因为在ListBlocks
集合中有一个元素的Value
集合等于null。
这是SelectMany
的怪癖,我通常会使用类似
mCache.ListBlocks.SelectMany(e => e.Value ?? List<MyType>())
编辑:
仔细观察,这种情况只会引发NullReferenceException
,您收到的ArgumentNullException
更有可能来自ToDictionary
来电。
此外,您只需使用Select
方法进行评估,即可删除第二个KeyValuePair
调用以及令人痛苦的ToDictionary
构造函数:
Dictionary<long, IList<Cell>> ByBlock =
mCache.ListBlocks
.SelectMany(e => e.Value)
.Where(e => listBlocks.Contains(e.Key))
.ToDictionary(
block => block.Key,
block => DataMgr.GetMapping("CASH",block,GetKey(IdKeys, block), mType))
);
答案 2 :(得分:0)
这就是我喜欢凌乱的LINQ。它使读取和调试变得更加容易。
var allListBlockValues = mCache.ListBlocks.SelectMany(listBlock => listBlock.Value);
var matchingListBlockValues = allListBlockValues.Where(e => listBlocks.Contains(e.Key))
Dictionary<long, IList<Cell>> ByBlock = new Dictionary<long, IList<Cell>>();
foreach (var Block in matchingListBlockValues)
{
long key = Block.Key;
var value = DataMgr.GetMapping("CASH",Block,GetKey(IdKeys, Block), mType);
ByBlock.Add(key, value);
}