структуры изменения c# в Списке <T>

Зачем использовать троичные операторы и если-иначе, когда вы можете просто сделать это

#define sgn(x) x==0 ? 0 : x/abs(x)
15
задан Scott Weldon 25 August 2016 в 03:23
поделиться

5 ответов

Что касается подхода цикла for, то причина (и решение) для этого приведены в документации для ошибки компиляции :

Была предпринята попытка изменить значение тип, который создается в результате промежуточное выражение, но не хранится в переменной. Эта ошибка может возникают, когда вы пытаетесь напрямую изменить структуру в общем collection.

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

Итак, в вашем цикле for измените следующие строки:

catSlots[s].subItems.Clear();
catSlots[s].subItems = sortedSubTemp;   // ERROR: see below

... на:

slotInfo tempSlot = gAllCats[0].items[s];
tempSlot.subItems  = sortedSubTemp;
gAllCats[0].items[s] = tempSlot;

Я удалил вызов метода Clear , поскольку я не думаю, что это что-то добавляет.

14
ответ дан 1 December 2019 в 03:24
поделиться

Проблема, с которой вы столкнулись в вашем foreach , заключается в том, что структуры являются типами значений, и в результате переменная итерации цикла на самом деле не является ссылкой на структуру в список, а скорее копию структуры.

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

subItems.Clear () представляет меньшую проблему, потому что, хотя поле может быть копией элемента в списке, оно также является ссылкой на список (неглубокая копия).

Самым простым решением, вероятно, было бы изменение с Для этого от структуры к классу . Или используйте совершенно другой подход с для (int ix = 0; ix <...; ix ++) и т. Д.

4
ответ дан 1 December 2019 в 03:24
поделиться

Две указанные вами ошибки связаны с тем, что вы используете структуры, которые в C # являются типами значений, а не ссылочными типами.

В циклах foreach можно использовать ссылочные типы. . Если вы измените свои структуры на классы, вы можете просто сделать это:

    foreach(var item in gAllCats[c].items)
    {
        item.subItems = item.subItems.OrderBy(x => x.subNum).ToList();
    }

Со структурами это нужно будет изменить на:

    for(int i=0; i< gAllCats[c].items.Count; i++)
    {
        var newitem = gAllCats[c].items[i];
        newitem.subItems = newitem.subItems.OrderBy(x => x.subNum).ToList();
        gAllCats[c].items[i] = newitem;
    }

В других ответах есть лучшая информация о том, почему структуры работают иначе, чем классы, но я подумал, что могу помочь с часть сортировки.

1
ответ дан 1 December 2019 в 03:24
поделиться

Цикл foreach не работает, потому что sInf является копией структуры внутри элементов. Изменение sInf не изменит «фактическую» структуру в списке.

Clear работает, потому что вы не изменяете sInf, вы меняете список внутри sInf, и Ilist всегда будет ссылочным типом.

То же самое происходит, когда вы используете оператор индексации в IList - он возвращает копию вместо фактической структуры. Если компилятор разрешил catSlots [s] .subItems = sortedSubTemp; , вы будете изменять подэлементы копии, а не фактическую структуру. Теперь вы понимаете, почему компилятор говорит, что возвращаемое значение не является переменной - на копию нельзя ссылаться снова.

Есть довольно простое исправление - работать с копией,

2
ответ дан 1 December 2019 в 03:24
поделиться

Если subItems был изменен на конкретный список вместо интерфейса IList , то вы сможете использовать Сортировка .

public List<itemInfo> subItems;

Таким образом, весь ваш цикл выглядит следующим образом:

foreach (slotInfo sInf in gAllCats[c].items)
    sInf.subItems.Sort();

Это не потребует изменения содержимого структуры struct (как правило, это хорошо). Члены структуры struct по-прежнему будут указывать на одни и те же объекты.

Кроме того, существует очень мало веских причин для использования struct в C #. Сборщик мусора очень, очень хорош, и вам лучше использовать класс , пока вы не продемонстрируете узкое место выделения памяти в профилировщике.

Еще более кратко, если items ] в gAllCats [c] .items также является списком , вы можете написать:

gAllCats[c].items.ForEach(i => i.subItems.Sort());

Изменить: Ты слишком легко сдаешься! :)

Сортировку очень легко настроить. Например:

var simpsons = new[]
               {
                   new {Name = "Homer", Age = 37},
                   new {Name = "Bart", Age = 10},
                   new {Name = "Marge", Age = 36},
                   new {Name = "Grandpa", Age = int.MaxValue},
                   new {Name = "Lisa", Age = 8}
               }
               .ToList();

simpsons.Sort((a, b) => a.Age - b.Age);

Сортировка от младшего к старшему. (Разве вывод типа не хорош в C # 3?)

1
ответ дан 1 December 2019 в 03:24
поделиться
Другие вопросы по тегам:

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