修改字典值是可能的。什么是正确的方法?
我有填充的字典,我无法控制。
我需要修改值我该怎么做?
我把一个简单的例子放在一起来解释这个问题
class Program { static void Main(string[] args) { Dictionary CustomerOrderDictionary = new Dictionary(); CustomerOrderDictionary.Add(new Customer { Id = 1, FullName = "Jo Bloogs" },3); CustomerOrderDictionary.Add(new Customer { Id = 2, FullName = "Rob Smith" },5); //now I decide to increase the quantity but cannot do the below as value has no setter foreach (var pair in CustomerOrderDictionary) { if(pair.Key.Id==1) { pair.Value = 4;///ERROR HERE } } } } public class Customer { public int Id { get; set; } public string FullName { get; set; } }
有什么建议? 非常感谢
我建议您先确定哪些密钥需要修改,然后迭代这些修改。 否则,当你迭代它时,你最终会修改一个集合,这将引发exception。 例如:
// The ToList() call here is important, so that we evaluate all of the query // *before* we start modifying the dictionary var keysToModify = CustomerOrderDictionary.Keys .Where(k => k.Id == 1) .ToList(); foreach (var key in keysToModify) { CustomerOrderDictionary[key] = 4; }
这里的问题是对键入KeyValuePair
,它是一个只读对象,不能修改。 此外, KeyValuePair
集合是一种查看字典内容(不更改字典)的方法。
你想在这里做的只是直接修改字典。 KeyValuePair
的Key
可用于更新字典中的相同条目。
if(pair.Key.Id==1) { CustomerOrderDictionary[pair.Key] = 4; }
编辑
正如Jon指出的那样,赋值将使迭代器无效。 最简单但无效的路线是在循环开始时复制枚举器。
foreach (var pair in CustomerOrderDictionary.ToList())
这是另一种方法
1)创建一个新类
// wrapper class to allow me to edit a dictionary public class IntWrapper { public int OrderCount{ get; set; } }
2)更改此声明
Dictionary CustomerOrderDictionary = new Dictionary();
3)分配你的变量
pair.Value.OrderCount = 4;
foreach (Customer customer in customers.Keys) { if ( customer.Id == 1 ) customers[ customer ] = 4; }
CustomerOrderDictionary[1] = 4;
这是一种方法(仅指定值部分..):
CustomerOrderDictionary[new Customer { Id = 1, FullName = "Jo Bloogs" }]=4
请注意,“1”不是您词典中的键。 Customer
是,所以你必须使用它。
另请注意, Customer
应按照此处的说明实现IEquatable
好的,在您的示例中,您实际上只是找到Id
= 1的Customer
对象的条目并更新关联的值。 实际上,我认为在更新字典中的关联值之前,您的代码可能能够获得对您的目标Customer
对象的引用。 如果是这种情况,则不需要循环。
下面是一个非常简单的示例,其中不需要循环,因为您的代码已经引用了customer1
变量。 虽然我的示例过于简化,但概念是您可能通过迭代字典之外的其他方式获得对所需Customer
对象的引用。
static void Main(string[] args) { Dictionary CustomerOrderDictionary = new Dictionary(); Customer customer1 = new Customer { Id = 1, FullName = "Jo Bloogs" }; Customer customer2 = new Customer { Id = 2, FullName = "Rob Smith" }; CustomerOrderDictionary.Add(customer1, 3); CustomerOrderDictionary.Add(customer2, 5); // you already have a reference to customer1, so just use the accessor on the dictionary to update the value CustomerOrderDictionary[customer1]++; }
如果需要根据其他一些条件对多个Customer
对象执行某种更新,则可能需要循环。 以下示例假定您将拥有除存储Customer
对象的字典之外的某些集合,并且您可以使用该Customer
对象集合来标识需要更新字典中的关联值的那些集合。
static void Main(string[] args) { // presumably you will have a separate collection of all your Customer objects somewhere List customers = new List (); Customer customer1 = new Customer { Id = 1, FullName = "Jo Bloogs" }; Customer customer2 = new Customer { Id = 2, FullName = "Rob Smith" }; Customer customer3 = new Customer { Id = 3, FullName = "Rob Zombie" }; customers.Add(customer1); customers.Add(customer2); customers.Add(customer3); Dictionary CustomerOrderDictionary = new Dictionary(); CustomerOrderDictionary.Add(customer1, 3); CustomerOrderDictionary.Add(customer2, 5); // let's just say that we're going to update the value for any customers whose name starts with "Rob" // use the separate list of Customer objects for the iteration, // because you would not be allowed to modify the dictionary if you iterate over the dictionary directly foreach (var customer in customers.Where(c => c.FullName.StartsWith("Rob"))) { // the dictionary may or may not contain an entry for every Customer in the list, so use TryGetValue int value; if (CustomerOrderDictionary.TryGetValue(customer, out value)) // if an entry is found for this customer, then increment the value of that entry by 1 CustomerOrderDictionary[customer] = value + 1; else // if there is no entry in the dictionary for this Customer, let's add one just for the heck of it CustomerOrderDictionary.Add(customer, 1); } }
如果不是这种情况,并且您可用的Customer
对象的唯一来源是字典本身,那么在迭代之前,您需要将这些对象的某种克隆/复制到单独的列表/数组中。修改字典。 请参阅Jon Skeet对此案的回答; 他建议在字典的Keys
属性上使用Where
filter,并使用ToList
方法创建一个单独的List
实例以进行迭代。