C#におけるメソッド、およびそれに準じる構造について説明します。
C#におけるメソッド
C#におけるメソッドには、インスタンスメソッドと静的メソッドがあります。
インスタンスメソッド
クラスからインスタンスを生成して、そのインスタンスから実行するメソッドのことをインスタンスメソッドと呼びます。なお、このインスタンスメソッドがいわゆる普通のメソッドのことであり、次に述べる静的メソッドと区別する場合以外では単に「メソッド」と呼ばれる場合が多いです。
インスタンスメソッドの宣言
基本書式
[戻り値データ型] [インスタンスメソッド名]([データ型] [引数1], [データ型] [引数2], ... )
{
[処理]
return [戻り値];
}
コード例
public int SampleMethod(int a, int b)
{
int c = a + b;
return c;
}
戻り値のデータ型とインスタンスメソッド名を書き、それに続いて引数のデータ型とその変数名を定義します。そして、{ }内に実際の処理を書き、return文で戻り値を指定します。戻り値がない場合は、戻り値データ型をvoidとし、return文は省略します。また、アクセス修飾子が必要な場合は戻り値データ型の前に記述します。なお、インスタンスメソッドはクラスの構成要素であり、必ずいずれかのクラス内に記述されます。
コード例ではint型の変数a, bを受け取り、その演算結果の「a + b」をcという変数に格納して返すメソッドを表しています。これはreturn文に直接処理を書くことも可能で、以下のように簡略化することもできます。
public int SampleMethod(int a, int b)
{
return a + b;
}
なお、インスタンスメソッドの戻り値にインターフェースを指定することで、そのインターフェースを実装したオブジェクトを戻り値として指定することもできます。
メソッドの実行
基本書式
[インスタンス].[インスタンスメソッド]([引数1], [引数2], ... )
コード例
class Program
{
static void Main(string[] args)
{
SampleClass s = new SampleClass();
int retVal = s.SampleMethod(2, 3);
Console.WriteLine(retVal);
}
}
class SampleClass
{
//メソッドを定義する
public int SampleMethod(int a, int b)
{
return a + b;
}
}
インスタンスメソッドは必ずクラスに属していて、それをインスタンス化することで実行できます。それを実行するときはインスタンス名に続けてインスタンスメソッド名を記述して呼び出します。なお、( )内にはメソッドの宣言で定義された引数を指定してください。
静的メソッド
クラスからインスタンスを生成せずに、そのまま実行可能なメソッドのことを静的メソッドと呼びます。
静的メソッドの宣言
基本書式
static [戻り値データ型] [静的メソッド名]([データ型] [引数1], [データ型] [引数2], ... )
{
[処理]
return [戻り値];
}
コード例
public static int SampleStaticMethod(int a, int b)
{
return a + b;
}
静的メソッドの宣言では戻り値データ型の前にstaticキーワードで静的メソッドであることを明らかにします。また、静的メソッドは特定のインスタンスではなくクラスそのものに属しているものなので、インスタンスフィールドやインスタンスメソッドにアクセスすることはできません。静的メソッドからアクセスできるのはあくまでも静的フィールドや静的メソッドのみとなります。
静的メソッドの実行
基本書式
[クラス].[静的メソッド]([引数1], [引数2], ... )
コード例
class Program
{
static void Main(string[] args)
{
int retVal = SampleClass.SampleMethod(2, 3);
Console.WriteLine(retVal);
}
}
class SampleClass
{
//静的メソッドを定義する
public static int SampleStaticMethod(int a, int b)
{
return a + b;
}
}
静的メソッドはクラスに直接属しており、それを実行する際はクラス名に続けて静的メソッド名を指定します。この時、インスタンス経由で静的メソッドを使うことはできません。
コード例ではSampleClassクラスにSampleStaticMethodという静的メソッドを定義していて、それを5行目で呼び出しています。先ほどのインスタンスの際は「s.SampleMethod(2, 3);」としてメソッドを呼び出していましたが、静的メソッドでは「SampleClass.SampleMethod(2, 3);」として呼び出しており、インスタンスから呼び出しているかクラスから呼び出しているかがわかると思います。
メソッドのパラメータ修飾子(ref / out / in パラメータ修飾子)
C#のメソッドの引数は値渡しが基本ですが、refパラメータ修飾子、outパラメータ修飾子、inパラメータ修飾子をメソッドの引数の前に置くことで参照渡しとなります。それによって「引数に指定した変数の値を更新する」などのような動作が可能になります。「サイズの大きいデータ型であるためにただ単に参照渡しにしたい」という場合で、その値は変更したくない場合はinパラメータ修飾子を用います。
ここではそれらのパラメータ修飾子について見ていきましょう。
修飾子 | 意味 |
---|---|
ref | 参照渡しにすることで、そのメソッドの処理の結果に応じてその引数に指定した変数の値を更新する。 (引数に指定する変数はあらかじめ初期化してある必要がある) |
out | 参照渡しにすることで、そのメソッドの処理の結果をその引数に指定した変数に代入する。 (引数に指定する変数をあらかじめ初期化しておく必要はない) |
in | 読み取り専用で参照渡しにする。(引数に指定した変数を更新することはできない) |
ref パラメータ修飾子 / out パラメータ修飾子
基本書式
//ref パラメータ修飾子
[戻り値データ型] [メソッド名](ref [データ型] [引数1], [データ型] [引数2], ... )
{
[処理]
}
//out パラメータ修飾子
[戻り値データ型] [メソッド名](out [データ型] [引数1], [データ型] [引数2], ... )
{
[処理]
}
コード例
class Program
{
static void Main(string[] args)
{
SampleClass s = new SampleClass();
int tmp;
tmp = s.SampleMethod(2, 3);
int tmp_ref = 0;
s.SampleMethod_Ref(ref tmp_ref, 2, 3);
int tmp_out;
s.SampleMethod_Out(out tmp_out, 2, 3);
}
}
class SampleClass
{
//パラメータ修飾子を使わない例
public int SampleMethod(int a, int b)
{
return a + b;
}
//refパラメータ修飾子を用いたメソッドの例
public void SampleMethod_Ref(ref int z, int a, int b)
{
z = a + b;
}
//outパラメータ修飾子を用いたメソッドの例
public void SampleMethod_Out(out int z, int a, int b)
{
z = a + b;
}
}
メソッドの宣言において、引数のデータ型の前にrefパラメータ修飾子やoutパラメータ修飾子を配置します。また、メソッドの実行の際も引数の前にrefやoutを指定する必要があります。
コード例では27-30行目でrefパラメータ修飾子を用いたメソッドの宣言を、33-36行目でoutパラメータ修飾子を用いたメソッドの宣言を行っています。また、21-24行目では比較のためにパラメータ修飾子を用いないメソッドを宣言しています。7-14行目でそれぞれtmp_ref変数、tmp_out変数、そしてtmp変数に結果を格納していますが、その結果はすべて同じになります。ただし、refパラメータ修飾子を使う場合だけは、あらかじめ引数に指定する変数(tmp_ref)を初期化しておく必要があることに注意してください。
このようにrefパラメータ修飾子とoutパラメータ修飾子は、引数に指定した変数にメソッドの処理結果を返すという役割を果たし、メソッドの引数を戻り値のように扱うことができるという点がポイントですが、これは、パラメータ修飾子を付けた引数は参照渡しされているだけなので、その値をメソッド内で変更するとそれが参照している元の変数の数値が変更されるので、結果的にそのメソッドを実行するときに引数に指定した変数の値が更新されているということになります。
in パラメータ修飾子
基本書式
//in パラメータ修飾子
[戻り値データ型] [メソッド名](in [データ型] [引数1], [データ型] [引数2], ... )
{
[処理]
}
コード例
class Program
{
static void Main(string[] args)
{
SampleClass s = new SampleClass();
int tmp = s.SampleMethod_In(2, 3);
}
}
class SampleClass
{
//inパラメータ修飾子を用いたメソッドの例
public int SampleMethod_In(in int a, in int b)
{
return a + b;
}
}
inパラメータ修飾子の場合はrefパラメータ修飾子と同じように宣言し、使用することができます。ただし、inパラメータ修飾子では、メソッドの実行時は引数にinパラメータ修飾子を付与する必要はありません(付与しても構いません)。
また、inパラメータ修飾子では引数に指定した変数の値は変えられないので、例えば以下のように参照渡しで取得した引数に他の値を代入しようとするとコンパイルエラーになります。
public int SampleMethod_In(in int a, in int b)
{
a = 10; //エラー
return a + b;
}
特殊なメソッド
コンストラクタ
コンストラクタはクラスがnew演算子によってインスタンス化されるときに自動的に実行されるメソッドのことです。
基本書式
[クラス名]([データ型] [引数1], [データ型] [引数2], … )
{
[処理]
}
コード例
class Program
{
static void Main(string[] args)
{
SampleClass s = new SampleClass(5);
}
}
public class SampleClass
{
//コンストラクタの定義
public SampleClass(int a)
{
}
}
コンストラクタではメソッド名をクラス名と同じにします。また、戻り値のデータ型は不要です。アクセス修飾子は必要に応じてコンストラクタの先頭につけてください。引数を指定することも可能ですが、コンストラクタで指定した引数をnew演算子でクラスをインスタンス化する際に指定する必要があります。コンストラクタは引数の違うものを複数定義することも可能です。
コード例ではSampleClassクラスのコンストラクタを作成しています。引数ではint型の数値をとるようにしており、そのためSampleClassクラスのインスタンス化の際にint型を指定しています(5行目)。
Mainメソッド
Mainメソッドはプログラムを実行するときに一番最初に呼び出されるメソッドで、エントリーポイントのことです。すべてのプログラムはそれを実行するためには必ず1つのMainメソッドを持っている必要があります。
基本書式
static void Main(string[] args)
{
[処理]
}
コード例
class Program
{
//メインメソッドの定義
static void Main(string[] args)
{
Program pg = new Program();
}
}
Mainメソッドはメソッド名が「Main」である静的メソッドとして記述します。このMainメソッドはあくまでも静的メソッドであり、これを実行した段階ではまだ自身のクラス自体もインスタンス化していないので、必要に応じてコード例のようにMainメソッド上で自身のクラスもインスタンス化します。
メソッドに準じる構造
C#ではメソッドに準じる構造として以下のようなものが用意されています。
コメント