第7章 キャストとデータ変換:連載 改訂版 C#入門(1/5 ページ)
C#にはさまざまなデータ型があり、それらはキャストにより変換可能だ。しかしキャストは思わぬ結果を招くことがあり、使用に際しては注意が必要だ。
本記事は、(株)技術評論社が発行する書籍『新プログラミング環境 C#がわかる+使える』から許可を得て転載したものです。同書籍に関する詳しい情報については、本記事の最後に掲載しています。
C#にはさまざまなデータ型があり、それを必要に応じて使い分けることになる。しかし、細かく分ければ分けるほど、あるデータを別のデータ型に変換する必要が発生する。本章では、あるデータ型を別のデータ型に変換する方法と注意を説明する。
7-1 目に見えない変換
C#には、表現可能な精度つまり桁数が異なるデータ型がいろいろある。例えば、sbyteは127までしか表現できないが、shortは32767まで表現できる、といった違いがある。そのことから考えると、表現力が小さい変数の内容を表現力の大きい変数に移し替えるのは、何ら問題がないように思える。事実、プログラムを書いてみると、すんなりと、違うデータ型の変数に代入できる。
実際に試した例をList 7-1に示す。
1: using System;
2:
3: namespace Sample001
4: {
5: class Class1
6: {
7: [STAThread]
8: static void Main(string[] args)
9: {
10: sbyte b = 123;
11: short s = b;
12: int i = s;
13: long l = i;
14: Console.WriteLine("{0},{1},{2},{3}",b,s,i,l);
15: }
16: }
17: }
これは、10行目で「123」という小さな整数をsbyte型の変数に代入し、それから順次、より多くの桁数を表現できる変数に代入を続け、結果を14行目で一気に表示するというものだ。実際に実行した結果はFig.7-1のようになる。
このような、誰が考えても納得できるような単純な変換は、いちいち何かの命令を書き込んで示す必要はない。C#が暗黙のうちに変換してくれる。
7-2 暗黙の変換ができない場合
さて、List 7-1のサンプルは桁数が小さい変数から桁数が大きい変数に代入したから何の文句も出ないのだが、すべての場合がそうとは限らない。例えば、桁数が大きい変数から桁数が小さい変数に代入するようなプログラムを書いたら何が起こるだろうか? 実際に書いてみたのがList 7-2のソースだ。
1: using System;
2:
3: namespace Sample002
4: {
5: class Class1
6: {
7: [STAThread]
8: static void Main(string[] args)
9: {
10: long l = 123;
11: int i = l;
12: short s = i;
13: sbyte b = s;
14: Console.WriteLine("{0},{1},{2},{3}",b,s,i,l);
15: }
16: }
17: }
このソース・コードは、Fig.7-2のようにコンパイル時にエラーになる。
q:\awrite\gh\cs\wk2\samples\chapt7\sample002\class1.cs(11,12): error CS0029: 型 'long' を型 'int' に暗黙的に変換できません。
q:\awrite\gh\cs\wk2\samples\chapt7\sample002\class1.cs(12,14): error CS0029: 型 'int' を型 'short' に暗黙的に変換できません。
q:\awrite\gh\cs\wk2\samples\chapt7\sample002\class1.cs(13,14): error CS0029: 型 'short' を型 'sbyte' に暗黙的に変換できません。
このソース・コードでは、たまたま、123という非常に小さな値を扱っているので、問題なく動くように見える。しかし、一般論でいえば、桁数が大きい変数から桁数が小さい変数に代入するようなプログラムでは、大きな値が入っていたら、桁数があふれて代入できないかもしれない。これに対処する方法は2種類ある。1つは、実行時に桁があふれたらエラーにする方法で、BASICインタープリタなどによく見られる方法である。もう1つは、コンパイル時にそのような代入は警告にしたり、あるいはエラーにする方法である。実行時にいちいちオーバーフローをチェックすると処理速度がスローダウンしてしまうので、効率重視なら、後者のほうがベターである。C#は、そのような考え方により、コンパイルする段階で、例え扱う数字が小さくても、桁数のより小さなデータ型への変換はエラー扱いする。
しかし、プログラマーが何が起きるのか承知しているなら、桁数のより小さなデータ型への変換も記述することができる。そのためには、すでに紹介したキャストを使用する。キャストはデータ型の名前を括弧(())でくくったもので、変数や定数の先頭に付けることで、キャストに記述したデータ型にデータを変換することを明示的に示す。キャストを使って、代入されるデータと代入する変数のデータ型を一致させるように書き直したものが、List 7-3のソースである。
1: using System;
2:
3: namespace Sample003
4: {
5: class Class1
6: {
7: [STAThread]
8: static void Main(string[] args)
9: {
10: long l = 123;
11: int i = (int)l;
12: short s = (short)i;
13: sbyte b = (sbyte)s;
14: Console.WriteLine("{0},{1},{2},{3}",b,s,i,l);
15: }
16: }
17: }
これを実行するとFig.7-3のようになり、問題なく数値の受け渡しができていることが分かる。つまり、キャストによってデータ変換が適切に行われているのである。
Copyright© Digital Advantage Corp. All Rights Reserved.