2016-11-14 71 views
0

我有我Newtonssoft Json.Net反序列化這樣一個JSON文件:反序列化的JSONObject得到更新,然後的foreach失敗

/* Get current config */ 
dynamic json = JsonConvert.DeserializeObject<Speaker>(
         File.ReadAllText(AppDomain.CurrentDomain.BaseDirectory + "cfg\\speaker.json")); 

dynamic jsonDevice = json.DeviceList; 

/* Go through the List */ 
foreach (Tapi tapi in lvTapiSonos.Items) 
{  
    foreach (var line in jsonDevice) 
    { 
     foreach (var l in line) 
     { 
     /* If not in List already, add it */ 
     if (l.Key != tapi.Name) 
     { 
      /* Add to Config */ 
      json.DeviceList.Add(new Dictionary<string, List<Device>> 
      { 
       { 
       tapi.Name, 
       new List<Device> 
       { 
        new Device 
        { 
         Volume = "5", 
         Ip = currentEditIp, 
         Name = currentEditName 
        } 
       } 
       } 
      }); 
     } 
    } 
    } 
} 
string output = JsonConvert.SerializeObject(json, Formatting.Indented); 
       File.WriteAllText(AppDomain.CurrentDomain.BaseDirectory + "cfg\\speaker.json", output); 

不幸的只適用於第一foreach,因爲我得到一個例外「列表已經改變了,枚舉不能繼續,「(與我在德語中的類似)在foreach (var line in jsonDevice)行中。

我明白這意味着,jsonDevice已經更新(它現在顯示在調試一個多項目),但因爲我分配jsonDevice外的foreach,它是如何更新?當我更新foreach中的json Object時,產生了foreach var line in json.DeviceList產生錯誤似乎是合乎邏輯的,但爲什麼這仍然會發生?

知道的任何線索......

+1

我想這是通過引用創建,: 動態jsonDevice = JSON。DEVICELIST; –

+0

它確實是一個參考複製到相同的分配,從而導致在'foreach'循環修改中的問題 –

回答

3

Memberwiseclone foreach語句被用於通過收集迭代得到 您想要的信息,但不能用於從源集合添加或刪除 項目避免不可預知的副作用。 如果您需要添加或刪除源集合中的項目,請使用 for循環。 http://msdn.microsoft.com/en-us/library/ttw7t8t6.aspx

如上所述,您可以使用循環爲您的用例。但如果你調用ToList()或ToArray的,你可以得到的值,而不是在這裏的項目副本可以使用了迭代

dynamic jsonDevice = json.DeviceList.ToList(); 
+0

這裏是'ToList'的源代碼好點, https://referencesource.microsoft.com/#mscorlib /system/collections/generic/list.cs,d2ac2c19c9cf1d44 –

1

以下是ilegal代碼在這裏:

json.DeviceList.Add(new Dictionary<string, List<Device>> 

爲什麼?

foreach你得到一個枚舉的集合,這是read-only forward moving,你不能改變foreach循環內的原始來源。您正在訪問的jsonDevice,這是被修改

怎麼辦json.DeviceList收集的參考副本:

轉換爲for循環和索引訪問,那麼你可以改變任何集合你通過索引訪問和不帶連接枚舉

或者

改變原始集合

創建集合的深層副本,創建新對象並複製所有引用類型的所有值成員和深度副本。你可以覆蓋基本對象類