Почему удаление (DictionaryInstance [key]); потерпеть неудачу?

В моем приложении используется словарь

protected _categoryToValueDict:Dictionary = new Dictionary();

чтобы сопоставить что-то еще.

Теперь, в какой-то момент в приложении, мне нужно удалить определенный ключ из Dictionary.

Я реализовал этот простой метод:

    public function setCategoryNoValue( cat:TAModelCategory ):void {

        // delete( _categoryToValueDict[ cat ] );

        var old:Dictionary = _categoryToValueDict;

        _categoryToValueDict = new Dictionary();

        for ( var key:* in old ) {

            if ( key != cat ) {
                _categoryToValueDict[ key ] = old[ key ];
            }
        }

    }

Если я использую только [описание delete operator]

delete( _categoryToValueDict[ cat ] );

само приложение не бросает ошибки в нормальном режиме. Но как только я сериализую свою внешнюю структуру данных во внешний источник [в настоящее время SharedObject], приложение не может де-сериализовать позже.

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

Альтернатива должна быть идентичной. Не так ли?

Итак, мой вопрос: какая разница между двумя альтернативами?

PS: Этот вопрос может быть связан с моим предыдущим.

ОБНОВЛЕНИЕ-1

Adobe объясняет эту страницу:


Чтобы объект, на который ссылается myObject, имеет право на сбор мусора, вы должны удалить все ссылки на него. В этом случае вы должны изменить значение myObject и удалить ключ myObject из myMap, как показано в следующем коде:

myObject = null;
delete myMap[myObject];

Предположим, что это опечатка. Не следует ли читать это так:

delete myMap[myObject];
myObject = null;

Зачем передавать нулевой указатель на myMap в качестве ключа?

Ответ 1

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

Я думаю, что вы, возможно, обнаружили законную ошибку в кодировке AMF ActionScript (или в том, как класс Dictionary получает Seralized через AMF). Ошибка влияет на все, что использует AMF, поэтому такая же ошибка воспроизводится с помощью ByteArray, поэтому я собираюсь использовать ее для демонстрационных целей.

Рассмотрим следующий код:

        var d:Dictionary = new Dictionary(false);
        d["goodbye"] = "world";
        d["hello"] = "world";
        delete d["hello"]

        var ba:ByteArray = new ByteArray();
        ba.writeObject(d);

        var len:uint = ba.position; 
        ba.position = 0;
        for(var i:uint=0;i<len;i++) {
            trace(ba.readUnsignedByte().toString(16));
        }

Выход будет:

11 05 00 06 0f 67 6f 6f 64 62 79 65 06 0b 77 6f 72 6c 64

Теперь, если мы никогда не ставим "hello" в качестве ключа:

        var d:Dictionary = new Dictionary(false);
        d["goodbye"] = "world";

        var ba:ByteArray = new ByteArray();
        ba.writeObject(d);

        var len:uint = ba.position; 
        ba.position = 0;
        for(var i:uint=0;i<len;i++) {
            trace(ba.readUnsignedByte().toString(16));
        }

Вывод:

11 03 00 06 0f 67 6f 6f 64 62 79 65 06 0b 77 6f 72 6c 64

Обратите внимание, что длина точно такая же, однако они отличаются во втором байте.

Теперь посмотрим на сериализацию, если я не удаляю "hello":

11 05 01 06 0b 68 65 6c 6c 6f 06 0b 77 6f 72 6c 64 06 0f 67 6f 6f 64 62 79 65 06 02

Обратите внимание, что 05 во втором байте совпадает с тем, как мы его удалили. Я думаю, что это указывает количество предметов в словаре. Я говорю "я думаю", потому что я долгое время проделывал документацию на AMF0/3, пытаясь выяснить, что именно происходит здесь, потому что это не похоже на сериализацию словаря, но его довольно последовательная, но я этого не понимаю.

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

Ваш альтернативный метод работает, потому что вы строите новый словарь и заполняете его... Его "внутренний счетчик" только увеличивается, поэтому он работает как шарм.

Еще одно замечание: если вы установите d["Hello"] = undefined, он не генерирует исключение, но элемент не будет удален из словаря. Ключ становится сериализованным со значением undefined в потоке AMF. Таким образом, полученный байт-поток длиннее, чем если бы он никогда не был там.

Использование Object, похоже, не демонстрирует такого же поведения. Это не только не приводит к ошибке, созданный байт-код в большей степени соответствует документации AMF0/3, которую я могу найти у Adobe. И полученный "ключ" буквально отбрасывается из сериализации, как будто этого на самом деле никогда не было. Поэтому я не уверен, какой особый случай они используют для Dictionary (видимо, недокументированный тип данных AMF3 0x11), но он не воспроизводится правильно с удалением элементов из него.

Мне кажется, что это законная ошибка.

изменить

Итак, я немного потянулся и нашел других людей, говорящих о AMF-серилизации Dictionary.

0x11 : Dictionary Data Type
0x05 : Bit code: XXXX XXXY
     : If y == 0 then X is a reference to a previously encoded object in the stream
     : If y == 1 then X is the number of key/val pairs in the dictionary.

Итак, если этот случай 5&1 == 1 и 5>>1 == 2, поэтому он ожидает две пары ключ/вал в "плохой" сериализованной версии.

Ответ 2

Правильный синтаксис для оператора delete выглядит следующим образом:

delete _categoryToValueDict[ cat ];

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