我有填充的字典,我无法控制。
我需要修改值,我该怎么做?
我把一个简单的例子放在一起解释问题
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; }
}
有什么建议吗? 非常感谢
答案 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
实例以进行迭代。