宇宙仮面の
C# Programming

 
Image

structとclass: どちらを使えばいいの?

開発環境: Visual Studio 2003 

目次

  1. 目次
  2. 目的
  3. 参考書
  4. ソースコード
  5. 実行結果
  6. 改定記録

目的

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
という本質的な違いがあるので、注意が必要!です。
では、どちらを使えばいいのでしょうか。
特徴をまとめたのが次の表です。

structclass
タイプValue TypeReference Type
継承不可
インターフェース
メモリーアロケーションスタックヒープ
用途簡単な構造のもの継承が必要なもの、複雑な構造

struct は int などと同じ Value Type (値型)で、スタックにアロケートされます。つまり、ヒープよりアロケートする class より スタックポインターでアクセスする struct のほうが高速です。どちらにしてもメモリ上なので事実上それほどの速度差は出ないと思いますが、大量のデータを扱う場合には影響が出てくるはずです。

一般的には、int などと同様にプリミティブなデータ構造には struct が適しています。
複雑なデータ構造のものに関しては class が適しているといえるでしょう。
継承が必要な場合には、class でしか対応できません。

以下、サンプルコード。
メソッドの引数に渡すとき、struct は、値 が(コピーされ)渡されるのに対し、class は、リファレンスが渡される。
このため、次のサンプルプログラムのように、class ではメソッドに渡したリファレンスに対して操作が行われるのに対し、struct ではコピーした値に対して操作が行われるので、メソッドの中で値を変更しても呼び出し側には反映されない。

参考書

(1) MSDN System.TimeZoneクラス

スタティックコンストラクタのテスト用ソースコード

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);
                }
        }
}

実行結果

Image

改定記録


日付コメント
2004/5/23全体デザイン再構成
2002/3/4初版作成