Reputation: 5946
I have some code which is failing - actually I cannot edit it. Following here and I'm trying to figure out the operation of this code, i.e. what this is doing. Its failing, but I do not know where exactly.
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);
I'm getting the error: Value cannot be null
, but I do not know what value is null and since I cannot edit the code or run Lambda's in the immediate window, I'm having trouble debugging this. So any ideas on how it works or the better way to look at these lambdas?
Upvotes: 2
Views: 153
Reputation: 318
Here's what I like to do with messy LINQ. It makes it much easier to read and debug.
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);
}
Upvotes: 0
Reputation: 30892
Reformating the code a bit it looks like this:
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);
My best bet would be that the ListBlocks.SelectMany(e => e.Value)
call fails, because in the ListBlocks
collection there is a element that has a Value
collection equal to null.
This is a quirk of SelectMany
, and I usually go around it using something like
mCache.ListBlocks.SelectMany(e => e.Value ?? List<MyType>())
EDIT:
On closer view, that case just throws a NullReferenceException
, the ArgumentNullException
you are recieving is more likely to come from the ToDictionary
call.
Also, you could remove the second Select
call, as well as the painful-to-look-at KeyValuePair
constructior, by just using the ToDictionary
method to do the evaluation:
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))
);
Upvotes: 2
Reputation: 66449
It's a bit misleading since dictionaries have keys and values, but you'll get that error when trying to insert a null
key into a Dictionary
(you're allowed to have null
values in a dictionary).
I think you can filter out null
values earlier on in your query so you don't end up with a null
key later on. I added a condition for && 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);
Upvotes: 3