Code Fix

中級

Unable to cast object の原因と直し方

object型に格納された値型(ボックス化)を、元の型と異なる型でアンボックスしようとすると発生します。

エラーメッセージの読み方

Unhandled exception. System.InvalidCastException: Unable to cast object of type 'System.Int32' to type 'System.Int64'.
System
名前空間 — System なら標準の基本例外です
InvalidCastException
例外クラス — 何が起きたか。ここを検索するのが最短です
Unable to cast object of type 'System.Int32' to type 'System.Int64'.
詳細メッセージ — どの値が問題だったか
at Program.Main(String[] args) in Program.cs:line 4
発生箇所 — スタックトレースの先頭行

このエラーが出る典型パターン

パターン1

 1  class Program {
 2      static void Main(string[] args) {
 3          object obj = 10;
 4          var n = (long )obj;
                       ^
 5          System.Console.WriteLine(n);
 6      }
 7  }
Unhandled exception. System.InvalidCastException: Unable to cast object of type 'System.Int32' to type 'System.Int64'. at Program.Main(String[] args) in Program.cs:line 4

ボックス化された値は、元の型と完全に一致する型にしかアンボックスできません。intをlongとして取り出すことはできません。

直し方: long を int にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  class Program {
 2      static void Main(string[] args) {
 3          object obj = 3.14;
 4          var n = (int    )obj;
                        ^
 5          System.Console.WriteLine(n);
 6      }
 7  }
Unhandled exception. System.InvalidCastException: Unable to cast object of type 'System.Double' to type 'System.Int32'. at Program.Main(String[] args) in Program.cs:line 4

doubleとしてボックス化された値をintとして直接アンボックスすることはできません。数値の変換とアンボックスは別物です。

直し方: int を double にします。

この問題を解いてみる →

パターン3

 1  class Program {
 2      static void Main(string[] args) {
 3          object obj = true;
 4          var n = (int   )obj;
                        ^
 5          System.Console.WriteLine(n);
 6      }
 7  }
Unhandled exception. System.InvalidCastException: Unable to cast object of type 'System.Boolean' to type 'System.Int32'. at Program.Main(String[] args) in Program.cs:line 4

boolとしてボックス化された値をintとして取り出すこともできません。C#のboolはintの別名ではありません。

直し方: int を bool にします。

この問題を解いてみる →

パターン4

 1  class Program {
 2      static void Main(string[] args) {
 3          object obj = 5;
 4          var n = (short)obj;
                       ^
 5          System.Console.WriteLine(n);
 6      }
 7  }
Unhandled exception. System.InvalidCastException: Unable to cast object of type 'System.Int32' to type 'System.Int16'. at Program.Main(String[] args) in Program.cs:line 4

ボックス化された値は元の型と完全に一致する型にしかアンボックスできません。

直し方: short を int にします。

この問題を解いてみる →

パターン5

 1  class Program {
 2      static void Main(string[] args) {
 3          object obj = 'a';
 4          var n = (int   )obj;
                        ^
 5          System.Console.WriteLine(n);
 6      }
 7  }
Unhandled exception. System.InvalidCastException: Unable to cast object of type 'System.Char' to type 'System.Int32'. at Program.Main(String[] args) in Program.cs:line 4

charとしてボックス化された値をintとして直接アンボックスすることはできません。

直し方: int を char にします。

この問題を解いてみる →

よくある誤解

int→longのような暗黙の数値変換は普段は自動で行われますが、アンボックスの際は元の型と完全に一致していないと失敗します。数値変換とアンボックスは別の規則です。

実務での勘所

ボックス化は単に型変換のルールの話にとどまらず、実行速度にも影響します。値型をobjectとして扱うたびにヒープへの割り当てが発生し、ガベージコレクションの対象が増えます。.NET 1.xの時代にはArrayListのような非ジェネリックなコレクションしか無く、int型の値を格納するたびに暗黙にボックス化が発生していました。.NET 2.0でジェネリクスが導入されList<int>のような型安全なコレクションが使えるようになったのは、この意図しないボックス化を無くし、実行速度を改善するという目的も大きな動機の1つでした。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)