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

发布于 2024-09-10 03:55:32 字数 2379 浏览 8 评论 0原文

我正在为 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

弱骨蛰伏 2024-09-17 03:55:32

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

在您的列表示例中,您有一个 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 for Dictionary.

In your list example you have a List<MyMutableType> and you update a Property 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 a MyNotMutableType instance in a certain position with another MyNotMutableType instance, you're not trying to simply change a Property 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 the MyMutableType.

Hope this help (and sorry for my poor english)

风吹短裙飘 2024-09-17 03:55:32

您收到的错误不是因为在枚举集合时无法修改字典,这是运行时错误。正如错误所述,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.

为你拒绝所有暧昧 2024-09-17 03:55:32

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

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

感谢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..

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

Thanks andyp & digEmAll

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文