Lambda函数c#含义

时间:2014-04-17 11:39:22

标签: c# linq lambda

我有一些失败的代码 - 实际上我无法编辑它。在这之后,我试图找出这段代码的操作,即这是做什么的。它失败了,但我不知道到底在哪里。

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?

3 个答案:

答案 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);
}