Lambda函数c#的含义
本文关键字:函数 Lambda | 更新日期: 2023-09-27 17:58:49
我有一些代码失败了-实际上我无法编辑它。下面是我试图弄清楚这段代码的操作,即它在做什么。它失败了,但我不知道具体在哪里。
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,所以我在调试时遇到了问题。那么,关于它是如何工作的,或者看待这些Lambda的更好方法,有什么想法吗?
这有点误导,因为字典有键和值,但在尝试将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);
重新格式化代码,如下所示:
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
调用。
此外,只需使用ToDictionary
方法进行评估,就可以删除第二个Select
调用,以及查看KeyValuePair
构造函数时的痛苦:
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))
);
以下是我喜欢用凌乱的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);
}