2014-04-17 2 views
2

나는 실패하고있는 어떤 코드를 가지고있다 - 실제로 그것을 편집 할 수 없다. 다음은이 코드의 작동, 즉 이것이 무엇을하는지 알아 내려고합니다. 그 실패,하지만 난 정확히 모르겠어요. Value cannot be null,하지만 내가 코드를 편집 또는 람다의 직접 실행 창에, 나는 문제가이 문제를 디버깅하는 데 문제가 실행할 수 없기 때문에 내가 널 어떤 값을 알고하지 않습니다람다 함수 C# 의미

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); 

나는 오류를 받고 있어요. 어떻게 작동하는지 또는이 람다를 보는 더 좋은 방법에 대한 아이디어가 있습니까?

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 컬렉션 null에 동일한 Value 콜렉션이있는 요소가 있기 때문에 ListBlocks.SelectMany(e => e.Value) 호출이 실패 할 것입니다 : 코드에게 그것은 다음과 같습니다 조금 Reformating

+3

lambdas의 고통에 오신 것을 환영합니다. (실제로는 좋아하지만 처리 오류는 고통입니다.) 몇 가지 라이너로 다시 나누어서 다시 실행하고 어떤 진술이 문제를 일으키는 지 알아내는 것이 좋습니다. – Liath

+0

@Liath 전적으로 두 번째로 - 나는 람다 식을 좋아하지만, 불행히도 디버깅 중에는 새로운 람다 식을 공식화 할 수 없습니다! – Codor

+1

@Codor 좋은 지적. 명확히하기 위해 나는 var a = mCache.ListBlocks.SelectMany();를 의미한다. var b = a.Where(); var c = b.Select() 등등 ... 그것은 끔찍하지만 범인을 찾기 위해 코드를 수정해야합니다. – Liath

답변

3

그것은 약간 오해의 소지를 사전에는 키와 값이 있기 때문에 null 값을 사전에 입력 할 수 있도록 null 키를 Dictionary에 삽입하려고하면 오류가 발생합니다.

나중에 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); 
2

.

SelectMany의 특질이며, 나는 보통 같은 것을 사용하여 주위에 이동

mCache.ListBlocks.SelectMany(e => e.Value ?? List<MyType>()) 

편집 :
가까이보기에 가,이 경우 그냥 ArgumentNullException 당신이 잡된다 NullReferenceException, 발생 ToDictionary 전화에서 올 가능성이 큽니다. 또한

, 당신은 두 번째 Select 전화뿐만 아니라, 제거 할 수있는 고통 - 투 - 룩에서 KeyValuePair constructior, 단지 평가를 수행 할 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)) 
     ); 
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); 
}