修改字典值是可能的。什么是正确的方法?

时间:2010-10-19 18:16:55

标签: c#

我有填充的字典,我无法控制。

我需要修改值,我该怎么做?

我把一个简单的例子放在一起解释问题

class Program
{
    static void Main(string[] args)
    {


        Dictionary<Customer, int> CustomerOrderDictionary = new Dictionary<Customer, int>();

        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; }
}

有什么建议吗? 非常感谢

7 个答案:

答案 0 :(得分:8)

我建议您找出哪些密钥需要先修改 ,然后迭代这些修改。否则,当你迭代它时,你最终会修改一个集合,这将引发异常。例如:

// 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;
}

答案 1 :(得分:6)

这里的问题是对被键入KeyValuePair,这是一个只读对象,无法修改。此外,KeyValuePair集合是查看字典内容(不更改字典)的一种方式。

这里你想要做的只是直接修改字典。 Key中的KeyValuePair可用于更新字典中的相同条目。

if(pair.Key.Id==1) {
  CustomerOrderDictionary[pair.Key] = 4;
}

编辑

Jon指出,赋值将使迭代器无效。最简单但无效的路线是在循环开始时复制枚举器。

foreach (var pair in CustomerOrderDictionary.ToList())

答案 2 :(得分:1)

这是另一种方法

1)创建一个新类

 // wrapper class to allow me to edit a dictionary
public class IntWrapper
{
    public int OrderCount{ get; set; }
}

2)更改此声明

  Dictionary<Customer, IntWrapper> CustomerOrderDictionary = new Dictionary<Customer, IntWrapper>();

3)分配你的变量

 pair.Value.OrderCount = 4; 

答案 3 :(得分:0)

foreach (Customer customer in customers.Keys)
{
    if ( customer.Id == 1 )
        customers[ customer ] = 4;
}

答案 4 :(得分:0)

CustomerOrderDictionary[1] = 4;

答案 5 :(得分:0)

这是一种方法(仅指定值部分..):

CustomerOrderDictionary[new Customer { Id = 1, FullName = "Jo Bloogs" }]=4  

请注意,“1”不是词典中的键。一个Customer,所以你必须使用它。

另请注意Customer应按照here

的说明实施IEquatable

答案 6 :(得分:0)

好的,在您的示例中,您实际上只是找到Customer = {1}}对象的条目并更新相关值。在实践中,我认为在更新字典中的关联值之前,您的代码可能能够获得对您的预期Id对象的引用。如果是这种情况,则不需要循环。

下面是一个非常简单的示例,其中不需要循环,因为您的代码已经引用了Customer变量。虽然我的示例过于简化,但概念是您可能通过迭代字典以外的其他方式获取对所需customer1对象的引用。

Customer

如果您需要根据其他一些条件对多个 static void Main(string[] args) { Dictionary<Customer, int> CustomerOrderDictionary = new Dictionary<Customer, int>(); 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<Customer> customers = new List<Customer>(); 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<Customer, int> CustomerOrderDictionary = new Dictionary<Customer, int>(); 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); } } 对象的唯一来源是字典本身,那么您需要执行某些类型的克隆/复制这些对象到单独的列表/ array在遍历字典进行修改之前。请参阅Jon Skeet对此案的回答;他建议在字典的Customer属性上使用Where过滤器,并使用Keys方法创建单独的ToList实例以进行迭代。