C# 在foreach循环中更新字典内容时出现问题
我正在为IEnumerable编写一个简单的通用更新扩展,该方法用于使用给定的键连接给定的2个业务对象或字典列表,并更新特定字段C# 在foreach循环中更新字典内容时出现问题,c#,dictionary,extension-methods,C#,Dictionary,Extension Methods,我正在为IEnumerable编写一个简单的通用更新扩展,该方法用于使用给定的键连接给定的2个业务对象或字典列表,并更新特定字段 public static void Update<TOuter, TInner, TKey>(this IEnumerable<TOuter> outer, IEnumerable<TInner> Inner, Func<TOuter, TKey> OuterKeySelector, Func<TInner, T
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);
}
}
}
}
公共静态无效更新(此IEnumerable外部、IEnumerable内部、Func OuterKeySelector、Func InnerKeySelector、Action更新程序)
{
ILookup innerLookup=Inner.ToLookup(InnerKeySelector,element=>element);
foreach(在外部的TOuter outerItem)
{
TKey key=OuterKeySelector(outerItem);
if(innerLookup.Contains(键))
{
foreach(innerLookup[key]中的TInner innerItem)
{
更新程序(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);
List obj1=新列表()
{
新建testObject(){fruitId=1,name=“mango”},
新的testObject(){fructId=2,name=“grapes”},
新的testObject(){fructId=2,name=“grapes”},
新建testObject(){fruitId=4,name=“kivi”},
};
List obj2=新列表()
{
新建testObject(){fruitId=2,name=“apple”},
新建testObject(){fructId=4,name=“orange”},
};
obj1.更新(obj2,
tx=>tx.FROUTID,
ty=>ty.FROUTID,
(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);
Dictionary first=新字典()
{
{“a”,1},
{“b”,2},
{“c”,9},
{“e”,5},
};
Dictionary second=新字典()
{
{“a”,8},
{“b”,2},
{“e”,20}
};
var-kk=0;
第一,更新(第二,
f1=>f1.Key,
s1=>s1.Key,
(f1,s1)=>f1.Value=s1.Value);
它给出了以下错误
属性或索引器
'System.Collections.Generic.KeyValuePair.Value'
无法分配给--它已被读取
只有
我知道MSDN有一个限制
枚举数可用于读取
集合中的数据,但它们
无法用于修改
基础集合
是否有一种黑客/解决方法可以以通用的方式实现相同的功能?如果您以与
字典
相同的方式查看列表
,那么您的代码似乎是合理的
在列表示例中,您有一个列表
,并在列表中的特定位置更新MyMutableType对象的属性
在您的字典示例中,您有一个字典
,您试图用另一个MyNotMutableType
实例替换某个位置的MyNotMutableType
实例,而不是简单地更改同一对象实例的属性
按照列表使用的方法,您应该有一个字典,如:
Dictionary
并且在更新程序委托中,您应该只更新MyMutableType
的属性
希望这有帮助(我的英语很差,很抱歉)您遇到的错误不是因为在枚举集合时无法修改词典,这是一个运行时错误。正如错误所说,KeyValuePair在Value参数上没有setter。因此不允许f1.Value==s1.Value。本质上,KeyValuePair是不可变的,因为您不能更改值
如果您想要这种类型的功能,我建议您创建一个更具体的更新,专门使用字典而不是IEnumerable
关于词典在被枚举时是只读的这一事实,我不知道答案。解决这个问题的另一个方法是切换内部和外部类。需要更新的类应该是内部的,因此这避免了可修改的集合进入枚举
second.Update(first1,
s1 => s1.Key,
f1 => f1.Key,
(f1, s1) => first1[s1.Key] = f1.Value);
谢谢,你试过第二个[f1.Key]=s1.Value吗?@andyp,它的第一个[f1.Key]=s1.Value。。我也试过了。。但它给出了一个错误“集合已修改;枚举操作可能无法执行”。如果确实要执行此操作,可以在扩展名中写入foreach(outer.ToList()中的TOuter outerItem)
。@digEmAll,不起作用。无论您做什么更改,它都会返回键值对的列表。:@Ramesh:我的意思是andyp解决方案(即second[f1.key]=s1.value
)加上我的(即foreach
扩展中的修改)。我已经测试过了,它可以工作(即使不是那么优雅)