代码之家  ›  专栏  ›  技术社区  ›  RameshVel

在foreach循环中更新字典内容时出现问题

  •  2
  • RameshVel  · 技术社区  · 14 年前

    我正在为IEnumerable编写一个简单的通用更新扩展,此方法用于使用给定的键联接给定的2个业务对象列表或字典,并更新特定字段。

    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.Collections.Generic.KeyValuePair.Value' 无法分配给--它已被读取 只有

    我知道有一个限制,由msdn

    枚举器可用于读取 集合中的数据,但它们 无法用于修改 基础集合。

    是否有黑客/解决方案以通用方式实现相同的功能?

    3 回复  |  直到 14 年前
        1
  •  2
  •   digEmAll    14 年前

    如果您以相同的方式查看您的代码 List 至于 Dictionary .

    在列表示例中,您有一个 List<MyMutableType> 你更新了一个 Property 列表中某个位置的MyMutableType对象。

    在您的字典示例中,您有一个 Dictionary<Key,MyNotMutableType> 你想用一个 MyNotMutableType 与另一个处于某个位置的实例 mynotmutable类型 例如,你不想简单地改变 财产 同一对象实例的。

    按照用于列表的方法,您应该有如下字典: Dictionary<Key,MyMutableType> 在更新程序委托中,您应该只更新 MyMutableType .

    希望能帮上忙(对不起我的英语不好)

        2
  •  1
  •   btlog Stefan Wick MSFT    14 年前

    您得到的错误不是因为枚举集合时无法修改字典,这是一个运行时错误。正如错误所说,keyValuePair在value参数上没有setter。所以f1.value==s1.value是不允许的。基本上,keyValuePair是不可变的,因为您不能更改值。

    如果您需要这种类型的功能,我建议您创建一个更具体的更新,它专门采用字典而不是IEnumerable。

    在解决字典在被枚举时是只读的这一事实方面,我不知道答案。

        3
  •  1
  •   RameshVel    14 年前

    解决这个问题的另一种方法是切换内部类和外部类。需要更新的类应该是内部的,这样可以避免modable集合进入枚举。

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

    谢谢 AndyP和Digemall