LoginSignup
1
1

More than 5 years have passed since last update.

"Warning: implicit downcast from Object to int" の対症療法と根治

Last updated at Posted at 2014-08-29

症状

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が使えます。これでObjectintに変換できます。

ToInt32で変換
var array : Array = [1, 2, 3];
var elem : int = System.Convert.ToInt32(array[1]);

対症療法2: ArrayごとList.<int>に変換

より安全なのは、Arrayの代わりに要素の型を一種類に固定したコンテナを使うことです。ここではすでにArrayがあるものとして、変換の方法を挙げていきます。

Listコンストラクタが変換に便利です。機能もほぼArrayの上位互換です。

List.<int>に変換
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が必要になります。目的と手段が逆になっている気もしますが、これが最もメモリが少なくすみます。

for文でコピー
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というそのもののメソッドがあります。しかし、プリミティブ型ではうまく動かないようです。

実行時にInvalidCastExceptionが起こる
var array : Array = [1, 2, 3];
var listOfInts : int[] = array.ToBuiltin(int) as int[]; 
var elem : int = listOfInts[1];

List#ToArrayで変換

富豪的には、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];のように宣言と初期化を同時に行うと型推論が働くので記述を短くすますことが出来ます。

他にこの警告が出た例があれば教えて下さい。

リンク

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1