C # Исключение при повторении с помощью набора значений словаря (int Key, & lt; T & gt; Value) [duplicate]

Вы можете использовать библиотеку Gson для синтаксического анализа строки JSON.

Gson gson = new Gson();
JsonObject jsonObject = gson.fromJson(jsonAsString, JsonObject.class);

String pageName = jsonObject.getAsJsonObject("pageInfo").get("pageName").getAsString();
String pagePic = jsonObject.getAsJsonObject("pageInfo").get("pagePic").getAsString();
String postId = jsonObject.getAsJsonArray("posts").get(0).getAsJsonObject().get("post_id").getAsString();

Вы также можете прокручивать массив «posts» следующим образом:

JsonArray posts = jsonObject.getAsJsonArray("posts");
for (JsonElement post : posts) {
  String postId = post.getAsJsonObject().get("post_id").getAsString();
  //do something
}
706
задан cdonner 5 July 2014 в 03:57
поделиться

12 ответов

Что может случиться, так это то, что SignalData косвенно меняет словарь подписчиков под капотом во время цикла и приводит к этому сообщению. Вы можете проверить это, изменив

foreach(Subscriber s in subscribers.Values)

To

foreach(Subscriber s in subscribers.Values.ToList())

Если я прав, проблема исчезнет

1293
ответ дан JaredPar 1 September 2018 в 08:34
поделиться

Примечание. В целом коллекции .Net не поддерживают перечисление и изменение в одно и то же время. Если вы попытаетесь изменить список коллекции, пока находитесь в середине перечисления, это вызовет исключение.

Таким образом, проблема этой ошибки заключается в том, что мы не можем изменять список / словарь во время цикла через. Но если мы итерируем словарь, используя временный список его ключей, мы можем изменить словарь, потому что теперь мы не итерируем словарь (и итерируем его коллекцию ключей).

sample:

//get key collection from dictionary into a list to loop through
List<int> keys = new List<int>(Dictionary.Keys);

// iterating key collection using simple for-each loop
foreach (int key in keys)
{
  // Now we can perform any modification with values of dictionary.
  Dictionary[key] = Dictionary[key] - 1;
}

Вот сообщение в блоге об этом решении.

И для глубокого погружения в stackoverflow: Почему эта ошибка возникает? ]

9
ответ дан Community 1 September 2018 в 08:34
поделиться
0
ответ дан ford prefect 1 September 2018 в 08:34
поделиться

На самом деле проблема заключается в том, что вы удаляете элементы из списка и ожидаете продолжить чтение списка, как будто ничего не случилось.

Что вам действительно нужно сделать, так это начать с конца и обратно к началу. Даже если вы удалите элементы из списка, вы сможете продолжить чтение.

4
ответ дан luc.rg.roy 1 September 2018 в 08:34
поделиться
1
ответ дан Mark Aven 1 September 2018 в 08:34
поделиться

Я видел много вариантов для этого, но для меня этот был лучшим.

ListItemCollection collection = new ListItemCollection();
        foreach (ListItem item in ListBox1.Items)
        {
            if (item.Selected)
                collection.Add(item);
        }

Затем просто прокрутите коллекцию.

Имейте в виду, что ListItemCollection может содержать дубликаты. По умолчанию в сборнике ничего не мешает дублированию. Чтобы избежать дублирования, вы можете сделать это:

ListItemCollection collection = new ListItemCollection();
            foreach (ListItem item in ListBox1.Items)
            {
                if (item.Selected && !collection.Contains(item))
                    collection.Add(item);
            }
2
ответ дан Mike 1 September 2018 в 08:34
поделиться

Когда абонент отказывается от подписки, вы меняете содержимое коллекции подписчиков во время перечисления.

Существует несколько способов исправить это, один из которых меняет цикл for, чтобы использовать явный .ToList():

public void NotifySubscribers(DataRecord sr)  
{
    foreach(Subscriber s in subscribers.Values.ToList())
    {
                                              ^^^^^^^^^  
        ...
95
ответ дан Mitch Wheat 1 September 2018 в 08:34
поделиться

Вы также можете заблокировать словарь подписчиков, чтобы он не изменялся всякий раз, когда он был зациклен:

 lock (subscribers)
 {
         foreach (var subscriber in subscribers)
         {
               //do something
         }
 }
33
ответ дан Mohammad Sepahvand 1 September 2018 в 08:34
поделиться

InvalidOperationException - произошло событие InvalidOperationException. Он сообщает, что «коллекция была изменена» в foreach-loop

Использовать оператор break, После удаления объекта.

ex:

ArrayList list = new ArrayList(); 

foreach (var item in list)
{
    if(condition)
    {
        list.remove(item);
        break;
    }
}
3
ответ дан nich 1 September 2018 в 08:34
поделиться

У меня была такая же проблема, и она была решена, когда я использовал цикл for вместо foreach.

// foreach (var item in itemsToBeLast)
for (int i = 0; i < itemsToBeLast.Count; i++)
{
    var matchingItem = itemsToBeLast.FirstOrDefault(item => item.Detach);

   if (matchingItem != null)
   {
      itemsToBeLast.Remove(matchingItem);
      continue;
   }
   allItems.Add(itemsToBeLast[i]);// (attachDetachItem);
}
2
ответ дан Nisarg Shah 1 September 2018 в 08:34
поделиться

Вы можете скопировать объект словаря подписчиков на объект временного словаря того же типа, а затем перебрать временный объект словаря с помощью цикла foreach.

0
ответ дан Rezoan 1 September 2018 в 08:34
поделиться

Более эффективным способом, на мой взгляд, является наличие другого списка, в котором вы заявляете, что вы помещаете все, что нужно «удалить». Затем, после завершения основного цикла (без .ToList ()), вы делаете еще один цикл над списком «для удаления», удаляя каждую запись, когда это происходит. Итак, в своем классе вы добавляете:

private List<Guid> toBeRemoved = new List<Guid>();

Затем вы меняете его на:

public void NotifySubscribers(DataRecord sr)
{
    toBeRemoved.Clear();

    ...your unchanged code skipped...

   foreach ( Guid clientId in toBeRemoved )
   {
        try
        {
            subscribers.Remove(clientId);
        }
        catch(Exception e)
        {
            System.Diagnostics.Debug.WriteLine("Unsubscribe Error " + 
                e.Message);
        }
   }
}

...your unchanged code skipped...

public void UnsubscribeEvent(Guid clientId)
{
    toBeRemoved.Add( clientId );
}

Это не только решит вашу проблему, это не позволит вам продолжать создавать список из вашего словаря, который стоит дорого, если там много подписчиков. Предполагая, что список абонентов, которые будут удалены на любой заданной итерации, будет меньше, чем общее число в списке, это должно быть быстрее. Но, конечно, не стесняйтесь профилировать его, чтобы быть уверенным, что это так, если есть какие-либо сомнения в вашей конкретной ситуации использования.

54
ответ дан Soner Gönül 1 September 2018 в 08:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: