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

发布于 2024-12-08 18:39:22 字数 1865 浏览 0 评论 0原文

我的应用程序使用字典

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( _categoryToValueDict[ cat ] );

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

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

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

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

PS:这个问题可能我的上一个

UPDATE-1

Adob​​e 解释 本页


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

myObject = null;
delete myMap[myObject];

假设这是一个拼写错误。它不应该这样读:

delete myMap[myObject];
myObject = null;

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

My app uses a Dictionary

protected _categoryToValueDict:Dictionary = new Dictionary();

to map something to something else.

Now, at a certain point in the application, I need to remove a certain key from the Dictionary.

I implemented this simple method:

    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 ];
            }
        }

    }

If I only use [description of the delete operator]

delete( _categoryToValueDict[ cat ] );

the app itself doesn't throw errors in normal mode. But as soon as I serialize its external data structure to an external source [currently SharedObject], the app isn't able to de-serialize it later on.

If I use the above coded manual iterative removal operation, the de-serialize operation works as expected and the model appears in the app.

The alternative should be identical. Shouldn't they?

Thus, my question: What's the difference between the two alternatives?

PS: This question might be related to my previous one.

UPDATE-1

Adobe explains on this page:


To make the object referenced by myObject eligible for garbage collection, you must remove all references to it. In this case, you must change the value of myObject and delete the myObject key from myMap, as shown in the following code:

myObject = null;
delete myMap[myObject];

Is suppose this to be a typo. Shouldn't it read like this:

delete myMap[myObject];
myObject = null;

Why pass a null-pointer to myMap as key?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

狼亦尘 2024-12-15 18:39:22

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

我认为您可能已经发现了 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,它不会抛出异常,但该项目不会从字典中删除。该密钥在 AMF 流中被序列化为 undefined 值。因此,生成的字节流比它不存在时要长。

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

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

编辑

所以我进一步挖掘,发现其他人在谈论 AMF 序列化一个字典

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,那么它期望“坏”序列化版本中有两个键/值对。

Okay, I just spent a good two hours or so looking into this, which is way more than I planning on spending looking at this. But I was intrigued.

I think you may have uncovered a legitimate bug in ActionScript's AMF encoding (or in how the Dictionary class gets seralized via AMF). The bug effects anything that uses AMF, so the exact same bug is reproduceable with a ByteArray, so I'm going to use that for demonstration purposes.

Consider the following code:

        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));
        }

The output will be:

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

Now what if we don't ever put the "hello" in as a key:

        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));
        }

The output then is:

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

Notice that the length is exactly the same, however they differ in the second byte.

Now lets look at the serialization for if I don't delete "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

Notice that 05 in the second byte is the same as when we deleted it. I think this is specifying the number of items in the Dictionary. I say "I think" because I dug through the documentation on AMF0/3 for quite a while trying to figure out exactly whats going on here, because it doesn't seem like this should be the serialization for a Dictionary, but its fairly consistent, but I don't get it.

So I think that's why you are hitting an exception (specifically the "End of file" error), because its still thinks there should be another item in the dictionary that it should be de-serializing.

Your alternate method works because you are constructing a new Dictionary and populating it... Its "internal counter" is only ever increasing, so it works like a charm.

Another thing to note, that if you set d["Hello"] = undefined, it does not throw an exception, but the item does not get removed from the dictionary. The key gets serialized with a value of undefined in the AMF stream. So the resulting byte-stream is longer than if it was never there.

Using an Object doesn't seem to exhibit this same behavior. Not only doesn't not produce an error, the generated bytecode is more in line with the AMF0/3 documentation I could find from Adobe. And the resulting "key" is literally dropped from the serialization, like it was in fact never there. So I'm not sure what special case they are using for Dictionary (apparently the undocumented AMF3 datatype 0x11), but it does not play right with deleting items out of it.

It seems like a legit bug to me.

edit

So I dug around a bit more and found other people talking about 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.

So if this case 5&1 == 1 and 5>>1 == 2, so it's expecting two key/val pairs in the "bad" serialized version.

不爱素颜 2024-12-15 18:39:22

删除运算符的正确语法如下:

delete _categoryToValueDict[ cat ];

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

Correct syntax for the delete operator is like this:

delete _categoryToValueDict[ cat ];

Although using parenthesis seems to compile fine, it's not the correct way.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文