actionscript-3 - 为什么 delete( DictionaryInstance[ key ] );失败?

标签 actionscript-3 apache-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运算符(operator)]
delete( _categoryToValueDict[ cat ] );

应用程序本身不会在正常模式下引发错误。但是只要我序列化 其外部数据结构到外部源 [当前 SharedObject ],应用程序无法反序列化 它稍后。

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

替代方案应该是相同的。他们不应该吗?

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

PS:这个问题可能与my previous one有关.

更新-1

Adobe 在 this page 上解释:

要使 myObject 引用的对象有资格进行垃圾回收,您必须删除对它的所有引用。在这种情况下,您必须更改 myObject 的值并从 myMap 中删除 myObject 键,如以下代码所示:
myObject = null;
delete myMap[myObject];

假设这是一个错字。不应该是这样的:
delete myMap[myObject];
myObject = null;

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

最佳答案

好吧,我只是花了两个小时左右的时间来研究这个,这比我计划花在这个上的要多得多。但我很好奇。

我认为您可能已经发现了 ActionScript 的 AMF 编码(或者 Dictionary 类如何通过 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似乎没有表现出同样的行为。不仅不会产生错误,生成的字节码更符合我可以从 Adob​​e 找到的 AMF0/3 文档。由此产生的“ key ”实际上从序列化中删除了,就像它实际上从未存在过一样。所以我不确定他们对 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 ,所以它期望在“坏”序列化版本中有两个键/值对。

关于actionscript-3 - 为什么 delete( DictionaryInstance[ key ] );失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7694075/

相关文章:

apache-flex - Linux下ActionScript3字体编译转码错误

actionscript-3 - 缩放和裁剪具有固定尺寸的图像

flash - 带有公共(public) getter 的内部 setter 不起作用

actionscript-3 - AS3计算特定坐标内的TUIO点

php - 你能举例说明在 flex 应用程序中使用 php 吗?

actionscript-3 - 如何使用添加的数据调度事件 - AS3

ios - Actionscript 3 代码可以在 iPhone 上运行吗?

actionscript-3 - 为什么要在 AS3 中使用命名空间?

apache-flex - 使用 Flex 进行网络摄像头录制是否严格要求媒体服务器(FMS、Red5、Wowza 等)?

apache-flex - 大型 Flex 应用程序的最佳实践?