2011-10-08 82 views
10

我的應用程序使用字典爲什麼刪除(DictionaryInstance [key]);失敗?

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

+1對於一個明確解釋的問題,並在發佈之前做一些研究。 – JeffryHouser

+0

查看您的代碼; 「刪除」方法的來源在哪裏? – JeffryHouser

+1

@ www.Flextras.com刪除是一個操作符,而不是一個方法。因此,我沒有提供一種方法。 – SteAp

回答

8

好的,我只花了兩個小時左右的時間來研究這個問題,這比我計劃花費的時間更多。但我很好奇。

我想你可能已經發現了ActionScript的AMF編碼中的一個合法的錯誤(或者如何通過AMF將Dictionary類seralized)。這個錯誤會影響使用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,所以它的預期的兩個關鍵/纈氨酸對在「壞」的序列化版本。

+0

太棒了!非常感謝你!我將提交一份錯誤報告。 – SteAp

+0

@SteAp:你有沒有想過提交錯誤報告?我今天遇到同樣的問題,我試圖在錯誤跟蹤器中搜索相關的錯誤報告,但找不到任何錯誤。 –

+0

嗯,不,我提出了一個錯誤,但Adobe甚至沒有回答。不確定,如果問題仍然存在於當前的FB/AIR版本中。需要檢查我的來源,我是如何解決問題的。稍後會回來.. – SteAp

0

delete operator正確的語法是這樣的:

delete _categoryToValueDict[ cat ]; 

雖然使用括號看起來編譯罰款,這不是正確的做法。

+0

經過一些測試後,似乎使用括號的工作方式與不使用它們相同,因此這可能對您無效。 – grapefrukt

+1

實際上,刪除操作符不需要括號。由於delete的參數是一個表達式,並且括號內的表達式也是一個有效的表達式,所以寫入delete(...)是完全合法的。 – SteAp