在 foreach 循环中更新字典内容时出现问题
我正在为 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
枚举器可用于读取 集合中的数据,但它们 不能用于修改 底层集合。
是否有一种黑客/解决方法可以以通用方式实现相同的功能?
I am writing a simple generic update extension for IEnumerable, this method used to join given 2 List of business objects or dictionaries using the given keys and updating the specific field.
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);
}
}
}
}
This works fine in normal objects, for ex:
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);
But, i cannot use this method with dictionary,
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);
it gives the below error
Property or indexer
'System.Collections.Generic.KeyValuePair.Value'
cannot be assigned to -- it is read
only
I know there is a restriction, by MSDN
Enumerators can be used to read the
data in the collection, but they
cannot be used to modify the
underlying collection.
is there a hack/workaround to achive the same functionality in a generic manner?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果您以与
List
和Dictionary
相同的方式查看代码,那么您的代码似乎是合理的。在您的列表示例中,您有一个
List
,并且您更新了列表中某个位置的 MyMutableType 对象的Property
。在您的字典示例中,您有一个
Dictionary
并且您尝试用另一个MyNotMutableType
替换某个位置的MyNotMutableType
实例例如,您并不是试图简单地更改同一对象实例的Property
。按照用于 List 的方法,您应该有一个类似以下的字典:
Dictionary
并且在更新程序委托中,您应该只更新MyMutableType
的属性。希望这有帮助(对我糟糕的英语感到抱歉)
Your code seems reasonable if you look it in the same manner for
List
as forDictionary
.In your list example you have a
List<MyMutableType>
and you update aProperty
of the MyMutableType object in a certain position in the list.In your dictionary example you have a
Dictionary<Key,MyNotMutableType>
and you are trying to substitute aMyNotMutableType
instance in a certain position with anotherMyNotMutableType
instance, you're not trying to simply change aProperty
of the same object instance.Following the approach used for List you should have a dictionary like:
Dictionary<Key,MyMutableType>
and in your updater delegate you should only update a Property of theMyMutableType
.Hope this help (and sorry for my poor english)
您收到的错误不是因为在枚举集合时无法修改字典,这是运行时错误。正如错误所述,KeyValuePair 在 Value 参数上没有设置器。所以 f1.Value == s1.Value 是不允许的。本质上 KeyValuePair 是不可变的,因为您无法更改值。
如果您想要这种类型的功能,我建议您创建一个更具体的更新,专门采用字典而不是 IEnumerable。
就解决字典在枚举时只读这一事实而言,我不知道答案。
The error you are getting is not because of the inability to modify the dictionary while you are enumerating a collection, this is a runtime error. It is, as the error says, that the KeyValuePair does not have a setter on the Value parameter. so f1.Value == s1.Value is not allowed. Essentially KeyValuePair is immutable as you can't change the values.
If you want this type of functionality I would recommend that you create a more specific Update that takes a Dictionary specifically rather than a IEnumerable.
In terms of working around the fact that dictionaries are readonly when the are being enumerated I don't know an answer.
解决这个问题的另一种方法是切换你的内在和外在。外部类。需要更新的类应该是内部的,这样就可以避免可修改的集合进入枚举。
感谢andyp &挖掘EmAll
Another way to solve this problem is to switch your inner & outer classes. Class that needs to be updated should be inner, so this avoids the modiable collection to enter into the enumuration..
Thanks andyp & digEmAll