2010-10-19 72 views
7

我有填充字典,我無法控制。修改字典值是可能的。什麼是正確的方法?

我需要修改值我該怎麼做?

我已經把諾迪例如共同問題的解釋

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

有什麼建議? 非常感謝

回答

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

嗨,感謝很多工作。我會嘗試看看是否適用於真正的code.thanks – user9969 2010-10-19 18:38:26

6

這裏的問題是,輸入對是輸入到KeyValuePair這是一個只讀對象,無法修改。此外,KeyValuePair集合是查看字典內容(不更改它)的一種方法。

你想在這裏做什麼只是直接修改字典。可以使用KeyValuePair中的Key來更新字典中的相同條目。

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

編輯

正如喬恩指出的分配將無效的迭代器。最簡單但無效的路徑是在循環開始時複製枚舉器。

foreach (var pair in CustomerOrderDictionary.ToList()) 
+2

除在修改字典中驗證迭代器:( – 2010-10-19 18:25:03

+0

嗨,謝謝你的回覆。試着通過doest不行。你把上面的代碼放在循環中嗎?如果不是什麼配對?對不起,因爲在這裏傻了 – user9969 2010-10-19 18:29:05

+0

@Jon哦,是的,忘了那部分。 – JaredPar 2010-10-19 18:31:59

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

這是錯誤的,字典的關鍵是不是一個整數(請參閱我的答案..) – 2010-10-19 18:26:16

0

這裏有一個辦法做到這一點(只是分配一個值的部分..):

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

注意, 「1」 是不是在你的字典的關鍵。一個Customer是,所以你必須使用它。

還要注意Customer應該實現IEquatable作爲解釋here

0

好吧,在你的例子你有效剛剛發現與Id = 1 Customer對象的條目,並更新相關的值。在實踐中,我認爲在更新詞典中的相關值之前,您的代碼可能能夠獲得對您想要的對象的引用。如果是這樣的話,那麼就不需要循環。

下面是一個非常簡單的示例,其中不需要循環,因爲您的代碼已經有對變量customer1的引用。雖然我的示例過於簡化,但概念是,您可以通過除迭代字典之外的其他方法獲取對所需對象的引用。

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對象的字典以外,您將擁有一些集合,並且您可以使用該集合的對象來標識其字典中的關聯值需要更新的集合。

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

如果是這種情況並非如此,你有可用的Customer對象的唯一來源是字典本身,那麼你就需要進行某種形式的那些對象的克隆/複製出一個單獨的列表/數組之前迭代字典進行修改。見Jon Skeet對此案的回答;他建議在字典的Keys屬性上使用Where過濾器,並使用ToList方法爲迭代目的創建單獨的List<Customer>實例。

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; 
+0

爲什麼負面投票?它適用於我...讚賞有建設性的反饋 – LamonteCristo 2011-10-25 05:17:50

+0

我只用一個'Value'字段定義了一個通用的'Holder ',而不是定義一個類來特別包裝'int'。另外,您忘記了如何將新的包裝添加到字典中。 – supercat 2012-06-26 20:07:32

+0

可能值得一提的一個優點是,當在自由多線程場景中使用時,您可以使用'ReaderWriterLockSlim'來守護字典,並且在更改字典本身時只需獲取'Writer'鎖定。在使用物品時,您可能希望獲得該物品的鎖定,但這不會干擾他人訪問字典。 – supercat 2012-06-26 20:09:48

相關問題