この記事は型変換と「キャスト」という重要な概念について解説します。
型変換
型変換とは、あるデータ型から別のデータ型への変換を指します。
例えば氷(solid:固体)を水(liquid:液体)に変えるようなものです。 この変換は外見を変えるだけでなく、その性質(ここでは状態)も変わります。 プログラミングでも同様に、一つのデータ型から別のデータ型に変換することが出来ます。
これが「型変換」の基本的な概念です。
Unity であれば、数字に関して、扱う型が異なるため、 整数型(int)のデータを浮動小数点型(float)に変換したり、その逆を行ったりすることがあります。 また、数字の型を文字列型に変換することもあります。
型変換の方法
型変換には「暗黙的な変換」と「明示的な変換」の2つの方法があります。
<暗黙的な変換>
暗黙的な変換は、プログラムが自動的に型変換を行うものです。情報の損失がない場合、つまり安全な場合に行われます。 そのため、特別に何かを記述する必要はなく、自動的に型の変換が行われます。
以下のコードでは int 型から float 型への暗黙的な変換を行っています。
int myInt = 10; float myFloat = myInt; // 暗黙的な変換① long myLong = myInt; // 暗黙的な変換②
この例では、myInt からmyFloat と MyLong へのは自動的に行われます。 なぜなら、intから float や longへの変換は、情報の損失がないからです。
これらは左辺と右辺の型が異なりますが、情報の損失がないため自動的に型の変換が行われる、暗黙的な変換の機能による代入処理です。
型に置き換えてみると、よく分かります。
int myInt = 10; float = int; // 暗黙的な変換① long = int; // 暗黙的な変換②
左辺と右辺の型が異なりますが、暗黙的な変換により、代入処理が成立しています。
<明示的な変換(キャスト)>
一方、明示的な変換は、プログラマーが明確に型変換を指示するものです。これをキャストと呼びます。 明示的な変換(キャスト)は、情報の損失が起こり得る場合に使用します。
キャストには (T)E という書式があります。 (T) に変換したい型、E に変換元になる変数を記述します。
以下のコードでは float 型から int 型への明示的な変換(キャスト)を行っています。
float myFloat = 10.5f; int myInt = (int)myFloat;
(int) の部分がキャストの書式における (T) です。 また myFloat の部分がキャストの書式における E を表しています。
このキャストにより myFloat の値が int 型に変換され、小数部分が切り捨てられます。 これが情報の損失です。本来であれば持っていたはずの小数部分の情報が無くなっていますね。
暗黙的な変換とは異なり、プログラマーが処理としてキャストの書式を記述して変換を指定するため、「明示的な変換」と表現されています。
キャストの実用例
それでは、実際のコード中でキャストがどのように使われるか見てみましょう。 このケースでは、異なるデータ型間で演算を行う際にキャストが利用されています。
int totalItems = 9; int itemsPurchased = 2; // キャストなしで計算 int percentPurchasedWithoutCast = itemsPurchased / totalItems * 100; Debug.Log("キャストなし: " + percentPurchasedWithoutCast); // キャストありで計算 float percentPurchasedWithCast = (float)itemsPurchased / totalItems * 100; Debug.Log("キャストありt: " + percentPurchasedWithCast);
まずキャストなしでパーセンテージを計算し、その結果をログに出力しています。 その後、キャストを行ってパーセンテージを再計算し、その結果をログに出力しています。
このコードを実行すると、"キャストなし" の出力は 0 となります。 これは itemsPurchased / totalItems が整数型で計算され、その結果が 0(小数点以下は切り捨てられる)になるためです。 パーセンテージを求めたいのですが、こちらの演算では想定している挙動になりません。
一方、"キャストあり" の出力は 22.2222222 となります。 これは itemsPurchased が float にキャストされ、その結果、小数点以下の情報が保持されるためです。 0 ではなくて、しっかりと小数の情報が演算されていることが分かります。
このように C#では、同じ型の値同士で割り算を行うと、結果もその型になります。 つまり、整数同士の割り算は整数の結果を生むので、小数点以下の情報が失われてしまいます。
そのため、ここでは itemsPurchased を float にキャストすることで、小数点以下の値を算出できるようにして、正確なパーセンテージを求めています。
ToStringメソッドによる型変換
ToStringメソッドは、C#のすべてのデータ型で使用できるメソッドです。
指定した変数の型を文字列型(string)に変換することができます。
int myInt = 10; string myString = myInt.ToString(); // "10"という文字列になります float myFloat = 9.78f; string myDoubleString = myFloat.ToString(); // "9.78"という文字列になります
この方法は、数値を文字列として表示したい場合や、数値を文字列操作の対象としたい場合に特に便利です。
UI に数値を文字列として表示したい場合に利用するケースが多いですね。
as キーワードによる型変換
as キーワードは、C#で型変換を試みるためのもう一つの方法です。 このキャストの方法は、asキーワードを使って指定した型へ変換を試み、もし変換が不可能であればnullを返します。 これは、データ型が実行時まで決定できない場合や、キャストが失敗したときに例外をスローせずに処理を続行したい場合に便利です。
Unity においては、ゲームオブジェクトやアセットなどをロードする際に Resources.Loadメソッドを使うことがあります。 このメソッドは Object型を返すため、ロードしたアセットを特定の型として扱うためには、明示的な変換(キャスト)が必要です。
最初にテクスチャの情報をロードした場合のサンプルコードです。
// リソースからテクスチャをロードしてTexture2D型にキャスト Texture2D texture = Resources.Load("Textures/MyTexture") as Texture2D; // ロードに成功したかどうかをチェック if (texture != null) { Debug.Log("Texture loaded successfully!"); } else { Debug.Log("Failed to load texture."); }
このコードでは as キーワードを使って Texture2D 型にキャストを試みています。 もしテクスチャのロードに失敗するか、またはロードしたアセットが Texture2D 型でない場合、キャストはnullを返し、エラーメッセージがログに出力されます。
この as キーワードを使ったキャストの特徴は、キャストが失敗してもプログラムの実行が停止しない点です。 したがって、予期せぬエラーからプログラムを守りつつ、型変換を安全に行うことができます。
同じようにプレハブをロードした場合のサンプルコードです。 プレハブは GameObject 型なので、ロードするときには as を使って Object 型から GameObject 型にキャストします。
// リソースからプレハブをロードしてGameObject型にキャスト GameObject prefab = Resources.Load("Prefabs/MyPrefab") as GameObject; // TODO ロードに成功したかどうか、null チェックをしましょう
まとめ
以上が型変換とキャストの基本的な説明となります。
特にキャストはC#プログラミングにおいて頻繁に用いられる概念ですので、その使い方を理解しておくことは非常に重要です。 しかし、キャストによって情報の損失が発生する可能性があるので、それを常に意識して使用することが求められます。
覚えておくと便利な機能の1つですので、是非、実際に活用して自分のスキルとして身につけていってください。