2010-07-16 64 views
2

我正在爲IEnumerable編寫一個簡單的通用更新擴展,此方法用於連接給定的2列表業務對象或字典使用給定的鍵和更新特定的字段。更新在foreach循環中字典的內容

public static void Update<TOuter, TInner, TKey>(this IEnumerable<TOuter> outer, IEnumerable<TInner> Inner, Func<TOuter, TKey> OuterKeySelector, Func<TInner, TKey> InnerKeySelector,Action<TOuter,TInner> updator) 
     { 
      ILookup<TKey, TInner> innerLookup = Inner.ToLookup(InnerKeySelector, element => element); 

      foreach (TOuter outerItem in outer) 
      { 
       TKey key = OuterKeySelector(outerItem); 
       if (innerLookup.Contains(key)) 
       { 
        foreach (TInner innerItem in innerLookup[key]) 
        { 
         updator(outerItem, innerItem); 
        } 
       } 
      } 

     } 

這工作正常,在正常的物體,例如:

 List<testObject> obj1 = new List<testObject>() 
     { 
      new testObject(){fruitId=1,name="mango"}, 
      new testObject(){fruitId=2,name="grapes"}, 
      new testObject(){fruitId=2,name="grapes"}, 
      new testObject(){fruitId=4,name="kivi"}, 
     }; 

     List<testObject> obj2 = new List<testObject>() 
     { 
      new testObject(){fruitId=2,name="apple"}, 
      new testObject(){fruitId=4,name="orange"}, 
     }; 

     obj1.Update(obj2, 
      tx => tx.fruitId, 
      ty => ty.fruitId, 
      (tx,ty)=>tx.name=ty.name); 

但是,我不能字典使用此方法,

 Dictionary<string, int> first = new Dictionary<string, int>() 
     { 
      {"a",1}, 
      {"b",2}, 
      {"c",9}, 
      {"e",5},    
     }; 
     Dictionary<string, int> second = new Dictionary<string, int>() 
     { 
      {"a",8}, 
      {"b",2}, 
      {"e",20}    
     }; 
     var kk = 0; 

     first.Update(second, 
      f1 => f1.Key, 
      s1 => s1.Key, 
      (f1, s1) => f1.Value = s1.Value); 

它提供了以下錯誤

財產或索引器 'System.Coll ections.Generic.KeyValuePair.Value」 不能被分配到 - 它是隻讀 只

我知道是有限制的,通過MSDN

枚舉數可用於讀取數據 在集合中,但它們不能用於修改 基礎集合。

是否存在一種黑客/解決方法以通用方式實現相同的功能?

+1

你試過第二[f1.Key] = S1 。值? – andyp 2010-07-16 09:53:08

+0

@andyp,它的第一個[f1.Key] = s1.Value ..我也試過這個..但它給出了一個錯誤「集合被修改;枚舉操作可能無法執行。」 – RameshVel 2010-07-16 10:00:49

+0

如果你真的想這樣做,你可以在你的擴展中編寫 'foreach(outer.ToList()中的TOuter outerItem)' – digEmAll 2010-07-16 10:21:50

回答

1

解決此問題的另一種方法是切換內部&外部類。類需要更新應該是內在的,所以這避免了modiable收集進入enumuration ..

 second.Update(first1, 
      s1 => s1.Key, 
      f1 => f1.Key, 
      (f1, s1) => first1[s1.Key] = f1.Value); 

感謝andyp & digEmAll

2

如果您以ListDictionary相同的方式查看,您的代碼似乎是合理的。

在您的列表示例中,您有一個List<MyMutableType>,並且您在列表中的某個位置更新MyMutableType對象的Property

在你的字典例如你有一個Dictionary<Key,MyNotMutableType>,你正試圖與其他MyNotMutableType例如某個位置替換一個MyNotMutableType實例,你不是要簡單地改變同一個對象實例的Property

按照用於列表的方法,您應該有一個字典,如: Dictionary<Key,MyMutableType>並且在您的更新程序委託中,您應該只更新MyMutableType的屬性。

希望這有助於(和對不起我的英文不好)

+0

感謝digEmAll,我明白你的觀點... :) – RameshVel 2010-07-16 10:05:55

1

你所得到的錯誤是不是因爲無法修改字典的,而你是枚舉集,這是一個運行時錯誤。正如錯誤所述,KeyValuePair在Value參數上沒有setter。所以f1.Value == s1.Value是不允許的。本質上KeyValuePair是不可變的,因爲你不能改變這些值。

如果你想要這種類型的功能,我會建議你創建一個更具體的更新,它需要一個特定的字典而不是IEnumerable。

在解決詞典被列舉時只讀的事實方面,我不知道答案。

+0

列表不能在枚舉過程中被修改... – digEmAll 2010-07-16 10:19:07