プログラミングを試してみたい人向けのC#プログラミングチュートリアル

クラスの作り方

POINT
  • C#のプログラムはクラスの塊でできている
  • クラスはデータと手続き(やること)がセットになったもの
  • クラスの作り方を学ぶ
目次

クラスとは

クラスはデータと手続き(やること)がセットになったものです。
何かの役割を持ったプログラムのまとまりとも言えます。
C#のプログラムはクラスが集まってできています。
クラスは次の形式で記述します。
class クラス名
{
    変数や処理など
}

ハローワールド

では、hello world!と表示するプログラムをクラスの処理として行ってみましょう。

サンプルプログラム
class Program
{
    static void Main()
    {
        // HelloWorldクラスを生成
        HelloWorld helloworld = new HelloWorld();
        // HelloWorldクラスの処理を呼び出し
        helloworld.WriteHelloWorld();
        
        System.Console.ReadKey();  // キー入力待ち
    }
}

// hello world!を表示するHelloWorldクラス
class HelloWorld
{
    public void WriteHelloWorld()
    {
        System.Console.WriteLine("hello world!");
    }
}
実行結果
hello world!

サンプルプログラムの実行方法はトップページを参照してください。

メイン処理を行うProgramクラスとは別にHelloWorldクラスを用意しました。
HelloWorldクラスにWriteHelloWorld()という処理を用意して、ここでhello world!を表示するようにしています。

インスタンス

クラスを使用するには、インスタンスを生成(インスタンス化)する必要があります。
前述のサンプルプログラムでは、下記の部分に当たります。
HelloWorld helloworld = new HelloWorld();

HelloWorld helloworldまでで変数としてクラスを用意しています。
new HelloWorld()を代入することで、実際にHelloWorldというクラスを作り出して使用できるようにしています。

なお、インスタンス化をしない場合は、コンパイルの際にエラーになります。
前述のサンプルプログラムを下記のように変更して、コンパイルしてみましょう。
(変更前)HelloWorld helloworld = new HelloWorld();
  ↓
(変更後)HelloWorld helloworld;

次のようなエラーメッセージが出て、コンパイルに失敗します。
エラーメッセージ「Program.cs(9,9): error CS0165: 未割り当てのローカル変数 'helloworld' が使用されました。」

変数の定義

クラス内で共通して使用する変数は、クラスの{}内に記載することで定義ができます。
クラス内で使用する際はthisを付けることでクラス変数へのアクセスであることを明示できます。
プログラムの途中で一時的に使用する変数はローカル変数と言います。

サンプルプログラム
class Program
{
    static void Main()
    {
        // HelloWorldクラスを生成
        HelloWorld helloworld = new HelloWorld();
        // HelloWorldクラスの処理を呼び出し
        helloworld.WriteHelloWorld();
        
        System.Console.ReadKey();  // キー入力待ち
    }
}

// hello world!を表示するHelloWorldクラス
class HelloWorld
{
    // クラス変数
    string message = "hello world!";
    
    public void WriteHelloWorld()
    {
        // ローカル変数
        string message = "WriteHelloWorldの変数";
        // クラス変数でWriteLine
        System.Console.WriteLine(this.message);
        // ローカル変数でWriteLine
        System.Console.WriteLine(message);
    }
}
実行結果
hello world!
WriteHelloWorldの変数

クラス変数とローカル変数が同名の場合、thisの記載がないとローカル変数を参照します。
ローカル変数に同名がない場合は、thisがなくてもクラス変数を参照します。
混同しないようにクラス変数の場合は頭に_を付けて、名前が重複しないようにしたり、クラス変数参照時は必ずthisを付けるなどの工夫が大切になります。

privateとpublic

クラス内の変数には、基本的にアクセス修飾子を付けます。
アクセス修飾子には、privateとpublicがあります。
privateは、クラス内でのみ使える変数です。
publicは、他のクラスからもアクセスできる変数です。

サンプルプログラム
class Program
{
    static void Main()
    {
        // HelloWorldクラスを生成
        HelloWorld helloworld = new HelloWorld();
        // publicの変数は他のクラスからアクセス可能
        helloworld.message = "hello world!";
        // HelloWorldクラスの処理を呼び出し
        helloworld.WriteHelloWorld();
        
        System.Console.ReadKey();  // キー入力待ち
    }
}

// hello world!を表示するHelloWorldクラス
class HelloWorld
{
    public string message = "";
    
    public void WriteHelloWorld()
    {
        System.Console.WriteLine(this.message);
    }
}
実行結果
hello world!

プロパティ

publicの変数は他のクラスから直接アクセスできますが、クラス間のデータのやり取りはプロパティの形式と使うのが一般的です。
プロパティは次の形式で記述します。
アクセスレベル 型名 プロパティ名
{
    set {
        受け取った値がvalueに入ってくる、valueに対する処理を記載
    }
    get {
        returnで渡す値を返す処理を記載
    }
}
一般的にプロパティ名は、privateな変数と区別するため同名の大文字始まりにします。

サンプルプログラム
class Program
{
    static void Main()
    {
        // HelloWorldクラスを生成
        HelloWorld helloworld = new HelloWorld();
        // publicの変数は直接アクセス可能
        helloworld.Message = "hello world!";
        // HelloWorldクラスの処理を呼び出し
        helloworld.WriteHelloWorld();
        
        System.Console.ReadKey();  // キー入力待ち
    }
}

// hello world!を表示するHelloWorldクラス
class HelloWorld
{
    // 変数はprivateで宣言
    private string message = "";
    
    // プロパティ
    public string Message {
        set { this.message = value; }
        get { return this.message; }
    }
    
    public void WriteHelloWorld()
    {
        System.Console.WriteLine(this.message);
    }
}
実行結果
hello world!

変数の定義やget、setの処理の記載も省略できる自動プロパティという記述方法もできます。

サンプルプログラム
class Program
{
    static void Main()
    {
        // HelloWorldクラスを生成
        HelloWorld helloworld = new HelloWorld();
        // publicの変数は直接アクセス可能
        helloworld.Message = "hello world!";
        // HelloWorldクラスの処理を呼び出し
        helloworld.WriteHelloWorld();
        
        System.Console.ReadKey();  // キー入力待ち
    }
}

// hello world!を表示するHelloWorldクラス
class HelloWorld
{
    // 自動プロパティ
    public string Message { set; get; }
    
    public void WriteHelloWorld()
    {
        System.Console.WriteLine(this.Message);
    }
}
実行結果
hello world!

プロパティは、下記のようにgetだけ記載した場合は読取専用になります。
アクセスレベル 型名 プロパティ名
{
    get {
        returnで渡す値を返す処理を記載
    }
}

setだけ記載した場合は書き込み専用になります。
自動プロパティでは、下記のように記載します。
アクセスレベル 型名 プロパティ名 { set; }

関数(メソッド)の定義

クラスはデータと手続き(やること)がセットになったものです。
やることはメソッドとして定義します。
メソッドは次の形式で記述します。
アクセスレベル 戻り値の型 メソッド名(引数の型 引数名,・・・)
{
    メソッドの処理
}
このページで紹介してきたサンプルプログラムで言うとWriteHelloWorldの部分がメソッドです。

戻り値

戻り値は、メソッドが値を返す場合に指定します。
メソッドの呼び出し時に=で左側に変数を記載することで変数に値をセットできます。
値を返さない場合、メソッドを定義するときに戻り値の型の部分にvoidと記載します。

サンプルプログラム
class Program
{
    static void Main()
    {
        // クラスを生成
        Class1 class1 = new Class1();

        // メッセージ表示
        class1.WriteMessage("メッセージを表示");
        
        // 入力値取得
        string s =  class1.ReadMessage();
        System.Console.WriteLine("入力値:"+s);
        // ↓下記のようにすれば変数を介さず、戻り値をそのまま扱うこともできます
        //System.Console.WriteLine("入力値:"+class1.ReadMessage());
        
        System.Console.ReadKey();  // キー入力待ち
    }
}

class Class1
{
    // 戻り値がないメソッド
    public void WriteMessage(string message)
    {
        System.Console.WriteLine(message);
    }
    // 戻り値があるメソッド
    public string ReadMessage()
    {
        System.Console.WriteLine("何かキーを入力してください");
        string s = System.Console.ReadLine();
        return s;
    }
}
実行結果
メッセージを表示
何かキーを入力してください
あいうえお
入力値:あいうえお

引数

引数はメソッドを定義するときにメソッド名の後ろの()内に(型 引数名)の形式で記載します。
引数を複数にする場合は、カンマ区切りで(型 引数名, 型 引数名)のように定義します。

引数名の後ろに=で値を指定することで省略可能な引数になります。
下記の例だと二つ目の引数を省略して クラス名.MethodName("引数1") のように呼び出すことができます。
例)public void MethodName(string arg1, int arg2 = 0)

引数の型の前にoutを付けることで、値を返す引数にすることができます。
例)public void MethodName(out string arg1)
outを使用する場合、呼び出すときにも渡す変数の前にoutを記載します。

サンプルプログラム
class Program
{
    static void Main()
    {
        // クラスを生成
        Class1 class1 = new Class1();

        // 引数ありで呼出
        class1.WriteMessage("引数指定あり", 1);
        
        // 引数を省略して呼出
        class1.WriteMessage("引数省略");
        
        // 引数で値を取得
        string s;
        class1.ReadMessage(out s);
        System.Console.WriteLine("入力値:"+s);
        
        System.Console.ReadKey();  // キー入力待ち
    }
}

class Class1
{
    public void WriteMessage(string arg1, int arg2 = 0)
    {
        System.Console.WriteLine(arg1 + ", " + arg2);
    }
    public void ReadMessage(out string message)
    {
        System.Console.WriteLine("何かキーを入力してください");
        message = System.Console.ReadLine();
    }
}
実行結果
引数指定あり, 1
引数省略, 0
何かキーを入力してください
あいうえお
入力値:あいうえお

コンストラクタ

コンストラクタは、特別なメソッドです。
コンストラクタには、クラスを生成した際に実行される処理を記載します。
コンストラクタは次の形式で記述します。
public クラス名(必要に応じて引数)
引数を使用する場合は生成する際、new クラス名(引数を指定)のように引数を指定します。

サンプルプログラム
class Program
{
    static void Main()
    {
        // クラスを生成
        Class1 class1 = new Class1("Class1を生成しました");
        
        System.Console.ReadKey();  // キー入力待ち
    }
}

class Class1
{
    // コンストラクタ
    public Class1(string message)
    {
        System.Console.WriteLine(message);
    }
}
実行結果
Class1を生成しました

static

メソッドにstaticを付けるをことで、クラスを生成せずに呼び出すことができるようになります。
このようなメソッドを静的メソッドを言います。
classにstaticを付けて静的クラスにすることもできます。
staticのメソッド内でクラス変数を使用する場合は、クラス変数にもstaticを指定する必要があります。
なお、staticのクラス変数の場合は、this.クラス変数名の指定ができません。
明示的に指定する場合は、thisの代わりにクラス名で指定します。
ほとんどメモリを使わない、かつ単体でよく使う処理を静的メソッドにすることが多いです。

サンプルプログラム
class Program
{
    static void Main()
    {
        // クラス生成不要で呼出し
        HelloWorld.WriteHelloWorld("hello world!");
        
        System.Console.ReadKey();  // キー入力待ち
    }
}

class HelloWorld
{
    // staticのメソッド内で使用する場合は変数もstaticを付ける
    static string _message = "";

    // static指定のメソッド
    static public void WriteHelloWorld(string message)
    {
        // staticの場合は実態がないためthisは使用できない、明示する場合はクラス名を付ける
        HelloWorld._message = message;
        System.Console.WriteLine(HelloWorld._message);
    }
}
実行結果
hello world!