struct と class で Point を作ってみましょう。
// class による Point
class ClassPoint
{
public int x, y;
public string str;
public ClassPoint(int x, int y)
{
this.x = x;
this.y = y;
this.str = "初期文字列";
}
}
// struct による Point
struct StructPoint
{
public int x, y;
public string str;
public StructPoint(int x, int y)
{
this.x = x;
this.y = y;
this.str = "初期文字列";
}
}
宣言が違うだけで、同じですね。しかし、
struct は、value type class は、reference type
という本質的な違いがあるので、注意が必要!です。 では、どちらを使えばいいのでしょうか。 特徴をまとめたのが次の表です。
| struct | class |
タイプ | Value Type | Reference Type |
継承 | 不可 | 可 |
インターフェース | 可 | 可 |
メモリーアロケーション | スタック | ヒープ |
用途 | 簡単な構造のもの | 継承が必要なもの、複雑な構造 |
struct は int などと同じ Value Type (値型)で、スタックにアロケートされます。つまり、ヒープよりアロケートする
class より スタックポインターでアクセスする struct
のほうが高速です。どちらにしてもメモリ上なので事実上それほどの速度差は出ないと思いますが、大量のデータを扱う場合には影響が出てくるはずです。
一般的には、int などと同様にプリミティブなデータ構造には struct が適しています。 複雑なデータ構造のものに関しては class が適しているといえるでしょう。 継承が必要な場合には、class でしか対応できません。
以下、サンプルコード。 メソッドの引数に渡すとき、struct は、値 が(コピーされ)渡されるのに対し、class は、リファレンスが渡される。 このため、次のサンプルプログラムのように、class ではメソッドに渡したリファレンスに対して操作が行われるのに対し、struct
ではコピーした値に対して操作が行われるので、メソッドの中で値を変更しても呼び出し側には反映されない。
|
using System;
namespace TestStruct
{
/// <summary>
/// structのテスト
/// </summary>
class Class1
{
// class による Point
class ClassPoint
{
public int x, y;
public string str;
public ClassPoint(int x, int y)
{
this.x = x;
this.y = y;
this.str = "初期文字列";
}
}
// struct による Point
struct StructPoint
{
public int x, y;
public string str;
public StructPoint(int x, int y)
{
this.x = x;
this.y = y;
this.str = "初期文字列";
}
}
// struct は value type
// struct StructPoint のパラメータをメソッドの中で変更する。
static private void testStruct (StructPoint sp)
{
sp.x = 99999;
sp.y = 99999;
sp.str = "変更されました。";
}
// class は reference type
// class ClassPoint のパラメータをメソッドの中で変更する。
static private void testClass (ClassPoint cp)
{
cp.x = 99999;
cp.y = 99999;
cp.str = "変更されました。";
}
static void Main(string[] args)
{
ClassPoint cp = new ClassPoint(1, 1);
Console.WriteLine("\nClassPoint = ({0}, {1}, {2}) に初期化されました。", cp.x, cp.y, cp.str);
Console.WriteLine("class ClassPoint のパラメータをメソッドの中で変更します。");
testClass(cp);
Console.WriteLine("結果は ClassPoint = ({0}, {1}, {2})", cp.x, cp.y, cp.str);
StructPoint sp = new StructPoint(1, 1);
Console.WriteLine("\nStructPoint = ({0}, {1}, {2}) に初期化されました。", sp.x, sp.y, sp.str);
Console.WriteLine("struct StructPoint のパラメータをメソッドの中で変更します。");
testStruct(sp);
Console.WriteLine("結果は StructPoint = ({0}, {1}, {2})", sp.x, sp.y, sp.str);
}
}
}
|