第5章 C#のデータ型


プログラムで扱うデータは、その特性によりいずれかのデータ型に属します。

では、C#のデータ型にはどのようなものがあるのでしょうか。C/C++のデータ型に似ていますが、全然違う側面も持っています。

C#で取り扱うデータ型は大きく、「値型(value type)」と「参照型(reference type)」に分かれます。

データ型 値型(value type)
参照型(reference type)

値型は、変数(valiable)を宣言すると、その変数はメモリ上に領域が確保されます。 これに、値を代入すると(初期化すると)、確保された領域にその値が設定されます。

参照型の変数もやはり、メモリ上にその領域が確保されます。変数を初期化するとき、初期値は、ヒープ領域に確保され、変数が確保している領域にはその参照が代入されます。

「参照」とは、メモリのアドレスのことです。

値型はstructキーワードで宣言されています。(構造体です。C/C++の構造体とは全く異なります。また、列挙型をのぞきます。)

参照型はclassキーワードで宣言されています。

この他に、C/C++のポインタ(Pointer type)も扱えます。

さて、この章では比較的取り扱いが簡単な値型の中でも数値を取り扱う数値型について解説します。その他の型についてはもう少し後で解説を行います。数値型は、整数型と実数型に大別されます。


C#型ビット長.NET型
数値型整数型 符号付きsbyte8ビットSystem.SByte
short16ビットSystem.Int16
int32ビットSystem.Int32
long64ビットSystem.Int64
符号なしbyte8ビットSystem.Byte
ushort16ビットSystem.UInt16
uint32ビットSystem.UInt32
ulong64ビットSystem.UInt64
実数型 浮動小数点数型float32ビットSystem.Single
double64ビットSystem.Double
10進データ型decimal128ビットSystem.Decimal

C#の型には.NET型というエイリアスがあります。これは、.NET Framework上で動作する他の言語と型を一致させるためのものです。

C#でプログラミングをする際、どちらの型を使ってもかまいません。また、プログラムの冒頭でusing System;とあれば、Systemを省略できます(System.Int32はInt32など)。 また、これらの型はstructで宣言されているので、次のような静的フィールドを利用できます。(フィールドについては後の章で解説)

MaxValue, MinValue
使い方は至って簡単で、Int32.MaxValueが、Int32型の最大値を表します。もちろんint.MaxValueとしても同じです。

// datatype01.cs

using System;

class datatype01
{
    public static void Main()
    {
        string format = "{0, -8}:{1}〜{2}", dot = "----------------";

        Console.WriteLine(format, "sbyte",sbyte.MinValue, sbyte.MaxValue);
        Console.WriteLine(format, "short", short.MinValue, short.MaxValue);
        Console.WriteLine(format, "int", int.MinValue, int.MaxValue);
        Console.WriteLine(format, "long", long.MinValue, long.MaxValue);
        Console.WriteLine(dot);
        Console.WriteLine(format, "byte", byte.MinValue, byte.MaxValue);
        Console.WriteLine(format, "ushort", ushort.MinValue, ushort.MaxValue);
        Console.WriteLine(format, "uint", uint.MinValue, uint.MaxValue);
        Console.WriteLine(format, "ulong", ulong.MinValue, ulong.MaxValue);
        Console.WriteLine(dot);
        Console.WriteLine(format, "float", float.MinValue, float.MaxValue);
        Console.WriteLine(format, "double", double.MinValue, double.MaxValue);
        Console.WriteLine(dot);
        Console.WriteLine(format, "decimal", decimal.MinValue, decimal.MaxValue);
        Console.WriteLine(dot);
    }
}
書式制御文字列で{0, -8}とあるのは、インデックス0の引数のスペースを8つ分取って、左詰で表示しなさいという意味です。{0, 8}なら右詰になります。

結果は、次のようになります。

xxxE+zzというのは、xxxかける10のzz乗という意味です。



さて、整数の10はint型の範囲にも入りますし、byte型、sbyty型、short, ushort, uint, long, ulong, float, double, decimal型の範囲にも属します。型を調べるGetTypeメソッドというのがあります。これは、どんなオブジェクトにでも使えます。

// literal01.cs

using System;

class literal01
{
    public static void Main()
    {
        string format = "{0}の型は{1}";
        
        Console.WriteLine(format, 10, 10.GetType());
        Console.WriteLine(format, 1.2, (1.2).GetType());

    }
}
実行結果は次のようになります。

これを見てわかるように単なる整数リテラルはint型(int型におさまらないときは、uint型に、それにもおさまらないときはlong, まだだめなときはulong型)とみなされます。

1.54のような小数点数はdouble型とみなされます。



では、次のような場合はどうなるのでしょうか。

byte x = 10;
リテラル10はint型です。int型より小さなbyte型に代入できるのでしょうか。 たまたま、int型の中でも小さな数字10なのでbyte型に代入してもよいのでしょうか。 この例の場合は、コンパイラは文句を言いません。
int x = 10;
byte b;
b = x;
この例では、コンパイルエラーとなります。代入しても大丈夫だとわかっているときは 型キャストをします。型キャストは
(データ型)式
で行います。
int x = 10;
byte b;
b = (byte)x;
とすれば、コンパイラは文句を言いません。しかし、型キャストをするときは慎重に行わないと、非常にわかりにくいバグが発生することがあります。
// cast01.cs

using System;

class cast01
{
    public static void Main()
    {
        byte a;
        int b = 10;
        a = (byte)b;

        Console.WriteLine("a = {0}", a);

        // 256はbyte型の範囲を超え桁あふれが起る
        b = 256;
        a = (byte)b;
        Console.WriteLine("a = {0}", a);
    }
}
このプログラムをコンパイルしても、「警告0,エラー0」で通ってしまいます。 しかし、実行すると

2回目のaの値が変ですね。これは、byte型に無理矢理255を代入したため桁あふれが起きたためです。あふれた桁は無視されるので0になってしまいます。



数値リテラルの型を明示的に示すこともできます。これには接尾辞をつけます。

分類接尾辞データ型
整数型なしint
L(またはl)long
U(またはu)uint
UL(またはul)ulong
実数型F(またはf)float
D(またはd)double
M(またはm)decimal

10Lと書くとこれは、long型の10という意味になります。

小数点数リテラルをdecimal型の変数に値を代入するときは必ずM(またはm)をつけないとエラーとなります。

二項式の内部ではデータ化を混在させることが可能です。この場合小さい型のは、大きい型に変換されます。(decimalだけは例外的で、1つがdecimalの時、他方がfloat,doubleである場合はエラーとなります。)

たとえば、int型 + byte型の時は、両方がint型とみなされます。

// cast02.cs

using System;

class cast02
{
    public static void Main()
    {
        int x = 10, y = 3;
        double z;

        z = x / y;
        Console.WriteLine("{0} / {1} = {2}", x, y, z);

        z = (double)(x / y);
        Console.WriteLine("{0} / {1} = {2}", x, y, z);

        z = ((double)x) / y;
        Console.WriteLine("{0} / {1} = {2}", x, y, z);
    }
}
実行結果は次のようになります。

x / yは、xもyもint型なのでx / yもint型です。この時x / y (=3.3333...)は切り捨てられ3となります。これが、double型に変換されzに代入されます。

第2の例では、(x / y)はint型でやはり、切り捨てられ3となり、これがdouble型にキャストされzに代入されます。

第3の例では、(double)x / yは型の大きい方に、合わせるのでyもdouble型となります。全体としてはdouble型で、その値は3.333...となります。これがzに代入されます。



[C# Index] [総合Index] [Previous Chapter] [Next Chapter]

Update 07/Aug/2006 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。