为什么删除(DictionaryInstance [key]);失败?

时间:2011-10-08 00:47:22

标签: actionscript-3 flex actionscript

我的应用使用词典

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运算符的说明]

delete( _categoryToValueDict[ cat ] );

应用程序本身不会在正常模式下抛出错误。但是,只要我序列化其外部数据结构[当前为SharedObject],应用就无法在以后对其进行反序列化

如果我使用上述编码手动迭代删除操作,则反序列化操作按预期工作,模型将显示在应用中。

替代方案应该相同。不应该吗?

因此,我的问题是:两种选择之间有什么区别?

PS:此问题可能my previous one相关。

UPDATE-1

Adob​​e在this page上解释:


要使myObject引用的对象符合垃圾回收的条件,必须删除对它的所有引用。在这种情况下,您必须更改myObject的值并从myMap中删除myObject键,如以下代码所示:

myObject = null;
delete myMap[myObject];

假设这是一个错字。不应该这样读:

delete myMap[myObject];
myObject = null;

为什么将空指针作为键传递给myMap?

2 个答案:

答案 0 :(得分:8)

好吧,我只花了两个小时左右的时间来研究这个问题,这比我计划花钱看多了。但我很感兴趣。

我认为您可能在ActionScript的AMF编码中发现了一个合法的错误(或者Dictionary类如何通过AMF进行​​了分类)。该bug会影响使用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,它不会抛出异常,但该项会从字典中删除。密钥在AMF流中以undefined的值序列化。因此,生成的字节流比从未存在的字节流更长。

使用Object似乎没有表现出同样的行为。不仅不会产生错误,生成的字节码更符合我从Adobe找到的AMF0 / 3文档。由此产生的“密钥”实际上从序列化中删除,就像它实际上从未出现过一样。所以我不确定他们使用Dictionary(显然是未记录的AMF3数据类型0x11)的特殊情况,但是它无法正确删除其中的项目。

这对我来说似乎是一个合法的错误。

修改

所以我挖了一下,发现其他人在谈论AMF serilization of a 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 == 15>>1 == 2,那么期望“坏”序列化版本中的两个键/值对。

答案 1 :(得分:0)

delete operator的正确语法是这样的:

delete _categoryToValueDict[ cat ];

虽然使用括号似乎编译得很好,但这不是正确的方法。