Невозможно изменить возвращаемое значение словаря, потому что это не переменная, использующая struct [duplicate]

Прежде всего, существует тот факт, что спецификация явно заявляет, что они являются объектами во многих местах, включая здесь , где он определяет термин «функция»:

function

член типа Object, который может быть вызван как подпрограмма

blockquote>

Эмпирически существует множество способов доказать это, но один из Проще всего назначить значение для него свойства:

var foo = function() { };
foo.myProperty = "my value";
console.log(foo.myProperty); // "my value"

Или использовать один в качестве прототипа (что необычно, но возможно) , что доказывает его, что только объекты могут быть прототипами:

var foo = function() { };
var obj = Object.create(foo);
console.log(Object.getPrototypeOf(obj) === foo); // true

31
задан NewProger 6 June 2011 в 17:47
поделиться

4 ответа

Индексатор вернет копию значения. Внесение изменений в эту копию ничего не сделает со значением в словаре ... компилятор останавливает вас от написания багги-кода. Если вы хотите изменить значение в словаре, вам нужно будет использовать что-то вроде:

// Note: copying the contents to start with as you can't modify a collection
// while iterating over it
foreach (KeyValuePair<string, MapTile> pair in tilesData.ToList())
{
    MapTile tile = pair.Value;
    tile.bgFrame = tile.bgFrame >= tile.bgAnimation ? 0 : tile.bgFrame + 1;
    tilesData[pair.Key] = tile;
}

Обратите внимание, что это также , избегая выполнения нескольких поисков без пользы Причина, по которой выполнялся ваш оригинальный код.

Лично я настоятельно рекомендую против иметь сменяемую структуру, чтобы начать с вас ...

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

// If MapTile is a reference type...
// No need to copy anything this time; we're not changing the value in the
// dictionary, which is just a reference. Also, we don't care about the
// key this time.
foreach (MapTile tile in tilesData.Values)
{
    tile.bgFrame = tile.bgFrame >= tile.bgAnimation ? 0 : tile.bgFrame + 1;
}
40
ответ дан Jon Skeet 21 August 2018 в 19:29
поделиться
  • 1
    ... и поэтому я отправил комментарий, а не ответ. Я знаю, когда возникает тема изменчивых структур, Джон Скит не может быть далеко позади. – Justin Niessner 6 June 2011 в 17:53
  • 2
    Ах, теперь я вижу, в чем проблема. Спасибо за помощь! – NewProger 6 June 2011 в 18:04
  • 3
    @JustinNiessner Anyways Jon Skeet предоставил очень хорошие и аккуратные ответы! – marc wellman 9 July 2012 в 09:51

Chance struct to Class

до:

public struct MapTile
{
    public int bgAnimation;
    public int bgFrame;
}

после:

public Class MapTile
{
    public int bgAnimation;
    public int bgFrame;
}
-1
ответ дан Darlan D. 21 August 2018 в 19:29
поделиться

tilesData[tile.Key] не является местом хранения (т. е. это не переменная). Это копия экземпляра MapTile, связанная с ключом tile.Key в словаре tilesData. Это то, что происходит с struct.

Что вам нужно сделать, это:

    MapTile tile = tilesData[tile.Key];
    if (tile.bgFrame >= tile.bgAnimation)
    {
        tile.bgFrame = 0;
    }
    else
    {
        tile.bgFrame++;
    }
    tilesData[tile.Key] = tile;
7
ответ дан jason 21 August 2018 в 19:29
поделиться
  • 1
    Я думал, что структуры не ссылочный тип, а переменный тип ... странный. Спасибо за объяснение. – NewProger 6 June 2011 в 18:05
  • 2
    И теперь я вижу, почему они считаются злыми :) Я, вероятно, изменю способ, которым это работает в будущем :) – NewProger 6 June 2011 в 18:06
  • 3
    struct - типы значений. Характерными особенностями типов значений являются то, что они копируются по значению, а равенство определяется равенством ценности. – jason 6 June 2011 в 18:12

Я бы предложил создать класс утилиты:

public class MutableHolder<T>
{
    public T Value;
    public MutableHolder(T value)
    {
        this.Value = value;
    }
}

Затем сохраните вновь созданный MutableHolder<MapTile> в каждом слоте словаря, а не сразу сохраните MapTile. Это позволит вам легко обновить фрагмент карты, связанный с каким-либо конкретным ключом, без необходимости изменять сам словарь (действие, которое в противном случае, как минимум, аннулирует счетчик, используемый вашим циклом foreach).

0
ответ дан supercat 21 August 2018 в 19:29
поделиться
Другие вопросы по тегам:

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