症状
var array : Array = [1, 2, 3];
var elem : int = array[1];
UnityScriptでArray
からint
を取り出そうとしたりすると、以下の様な警告に悩まされます。
Warning: implicit downcast from Object to int
原因
intをUnityScriptのArrayに入れてしまうと、int
がボックス化されてしまい、要素を取り出す時はすべてObject
扱いになります。そのため、取り出す際にはなんらかの変換が必要になります。
対症療法1: 取り出してからintに変換
UnityScriptのas
演算子によるキャストは参照型専用のため、array[1] as int
と書いてすませることはできません。
代用として、.NET標準のSystem.Convert.ToInt32が使えます。これでObject
をint
に変換できます。
var array : Array = [1, 2, 3];
var elem : int = System.Convert.ToInt32(array[1]);
対症療法2: ArrayごとList.<int>に変換
より安全なのは、Arrayの代わりに要素の型を一種類に固定したコンテナを使うことです。ここではすでにArrayがあるものとして、変換の方法を挙げていきます。
List
のコンストラクタが変換に便利です。機能もほぼArrayの上位互換です。
using System.Collections.Generic;
// ...
var array : Array = [1, 2, 3];
var listOfInts : List.<int> = new List.<int>(array);
var elem : int = listOfInts[1];
対症療法3: Arrayごとint[]に変換
int[]
も意外と機能は豊富です。伸び縮みこそできないものの、System.Arrayのスタティックメソッド群は頼りになります。
for文で変換
for
文を回してコピーする場合は、対症療法1のSystem.Convert.ToInt32
が必要になります。目的と手段が逆になっている気もしますが、これが最もメモリが少なくすみます。
var array : Array = [1, 2, 3];
var ints : int[] = new int[array.length];
for (var i = 0; i < ints.length; i++) {
ints[i] = System.Convert.ToInt32(array[i]);
}
var elem : int = ints[1];
ToBuiltinで変換 (使えたら)
Unityのリファレンスには、ToBuiltin
というそのもののメソッドがあります。しかし、プリミティブ型ではうまく動かないようです。
var array : Array = [1, 2, 3];
var listOfInts : int[] = array.ToBuiltin(int) as int[];
var elem : int = listOfInts[1];
List#ToArrayで変換
富豪的には、List
を経由してToArrayを使うのが記述が短くすみます。
var array : Array = [1, 2, 3];
var listOfInts : int[] = new List.<int>(array).ToArray();
var elem : int = listOfInts[1];
根治: Arrayを使わない
以上に紹介した方法はいずれも対症療法です。Array
を受け渡ししないのが安全性的にも速度的にも一番です。ほとんどの場合はList.<int>
で置き換えることができます。
筆者の場合は手を抜いてブラウザ用のJSONパーサを持ってきた時にこの警告に遭遇しました。その後Json.NETに乗り換えました。
他の原因
Array
を使わない時でも、以下のような記述をするとimplicit downcast
の警告が出ます。
var array : int[] = [1, 2, 3];
var elem;
elem = array[1];
var foo : int = elem;
これは変数elem
の型がデフォルトのObject
になったことによるものです。var elem : int;
と宣言しておくことで警告も速度悪化も避けることができます。他の方法として、var elem = array[1];
のように宣言と初期化を同時に行うと型推論が働くので記述を短くすますことが出来ます。
他にこの警告が出た例があれば教えて下さい。