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

Ste*_*eAp 11 apache-flex actionscript actionscript-3

我的应用程序使用字典

protected _categoryToValueDict:Dictionary = new Dictionary();
Run Code Online (Sandbox Code Playgroud)

将某事物映射到其他东西.

现在,在应用程序的某个点上,我需要删除某个键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 ];
            }
        }

    }
Run Code Online (Sandbox Code Playgroud)

如果我只使用[ 删除运算符的描述]

delete( _categoryToValueDict[ cat ] );
Run Code Online (Sandbox Code Playgroud)

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

如果我使用上面编码的手动迭代删除操作,反序列化操作按预期工作,模型出现在应用程序中.

替代方案应该是相同的.不应该吗?

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

PS:这个问题可能我以前的问题有关.

UPDATE-1

Adobe在此页面上解释:


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

myObject = null;
delete myMap[myObject];
Run Code Online (Sandbox Code Playgroud)

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

delete myMap[myObject];
myObject = null;
Run Code Online (Sandbox Code Playgroud)

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

J. *_*mes 8

好吧,我只花了两个小时左右的时间来研究这个问题,这比我计划花钱看待这个要多得多.但我很好奇.

我想你可能在ActionScript的AMF编码中发现了一个合法的错误(或者Dictionary通过AMF 如何通过AMF来分类).该bug会影响使用AMF的任何内容,因此完全相同的bug可以通过a重现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));
        }
Run Code Online (Sandbox Code Playgroud)

输出将是:

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));
        }
Run Code Online (Sandbox Code Playgroud)

然后输出是:

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,它不会抛出异常,但该项目并没有得到从字典中删除.密钥将使用undefinedAMF流中的值进行序列化.因此,生成的字节流比从未存在的字节流更长.

使用a Object似乎没有表现出同样的行为.不仅不会产生错误,生成的字节码更符合我从Adobe找到的AMF0/3文档.由此产生的"密钥"实际上从序列化中删除,就像它实际上从未出现过一样.所以我不确定他们使用的是什么特殊情况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.
Run Code Online (Sandbox Code Playgroud)

因此,如果这种情况下5&1 == 15>>1 == 2,所以它的预期的两个关键/缬氨酸对在"坏"的序列化版本.