我的应用使用词典
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
Adobe在this page上解释:
要使myObject引用的对象符合垃圾回收的条件,必须删除对它的所有引用。在这种情况下,您必须更改myObject的值并从myMap中删除myObject键,如以下代码所示:
myObject = null;
delete myMap[myObject];
假设这是一个错字。不应该这样读:
delete myMap[myObject];
myObject = null;
为什么将空指针作为键传递给myMap?
答案 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 == 1
和5>>1 == 2
,那么期望“坏”序列化版本中的两个键/值对。
答案 1 :(得分:0)