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的更好方法,有什么想法吗?

Lambda函数c#的含义

这有点误导,因为字典有键和值,但在尝试将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);
}