Hello, World
まずはC#の "Hello, World!!" を見てみましょう。
using System; // using宣言
namespace Sample // 'namespace (= 名前空間)'
{
class Hello // 'クラス' 宣言 - 開始
{
public static void Main(string[] args) // 'メソッド' 宣言 - 開始
{
// 標準出力に "Hello, World!!" と出力する. <--- コメント
Console.WriteLine("Hello, World!!");
} // 'メソッド' 宣言 - 終了
} // 'クラス' 宣言 - 終了
}
上記のコードを簡単に見ていきましょう。また、各項目の詳細は別ページにて解説しています。わからないことがあっても読み飛ばしてしまってください。
クラス
C#では基本的にクラスを使ってプログラミングを行います。
クラスというのは、プログラムの中で "ある特定の機能を担当する" かたまりです。 C#プログラミングではこの "クラス" を連携させることで一つのプログラムを作りあげていきます。
OOPの説明のときに詳細は記述しますが、この "クラス" というものは極力小さく作成することが望まれます。
ただし、小さすぎても良くない(=機能がない) です。そのため、クラス設計が非常に重要になります。
C#でのクラス宣言方法は以下のとおりとなっています。
class ClassName
{
// メソッドやフィールド、プロパティの定義
}
メソッド
class ブロックの中に定義されている要素のことを "メンバー" と言います。
メンバーには、フィールド・プロパティ・メソッド・コンストラクタなど、様々な要素がありますが、 その中でも特に重要なメソッドについて簡単に紹介します。
"メソッド" は、クラスの機能を表すために実装するメンバーのことです。 もっと簡単に言えば、そのクラスが行える "処理" のことをメソッドと呼んでいます。
メソッドの名前は自由に決められますが、"Main" メソッドだけはすでにC#によって予約されているメソッドのため、 使うことができません。"Main" メソッドは【 C#プログラムが最初に処理を始める開始地点 】という特殊な意味があります。
プログラムの開始地点という意味で、"エントリーポイント" とも言います。
C#でのメソッド宣言方法は以下のとおりとなっています。
class Sample
{
// -------------------------------------------------------------
// メソッドはクラス宣言ブロックの内側で定義します。
//
// [ 宣言方法 ]
// <アクセス修飾子> <その他キーワード> 返り値 メソッド名 (<引数>)
// {
// // メソッドブロック
// }
//
// static メソッド (= クラスメソッド)
public static void Hoge()
{
// ここに処理を記述する
}
// public メンバメソッド
public int Fuga()
{
// ここに処理を記述する
}
// private メンバメソッド
private string Piyo(int hoge)
{
// ここに処理を記述する
}
}
private や public といったキーワードは、"アクセス修飾子" といい、メソッドやプロパティ・フィールドへのアクセス権限を決めることができます。
詳細については別記事にて記載いたします。フィールド
クラスには "振る舞い(= メソッド)" 以外にも "状態(= State)" をもつものも数多く存在しています。
そういった場合に使われるものが "フィールド" です。フィールドは private 修飾子で宣言されるメンバ変数です。 そのため、外部からアクセスすることはできません。
クラスが持つ状態はなんらかのメンバメソッドが実行されることによって変化するため、そのクラス以外が "状態" を直接変更してしまうことを 防ぐために、基本的に private で宣言する必要があります(強制ではない)。
基本的に外部にクラス固有の値を公開する際は、後述する "プロパティ" を利用します。 しかし、特別な理由がない場合、クラス内部の値を公開するべきではありません。これについては別記事で紹介します。
フィールドは以下のように、クラス宣言内部にフィールド宣言します。
class Hoge
{
// -------------------------------------------------------------
// フィールドはクラス宣言ブロックの内側で定義します。
// フィールド名は慣例的に アンダースコア(_) から書き始めたりもします。
//
// [ 宣言方法 ]
// private <その他キーワード> 型名 フィールド名;
//
// string型 の _name 静的フィールドを宣言
private static string _name;
// int型 の _number フィールドを宣言
private int _number;
// 読み取り専用の double型 の _weight フィールドを宣言
private readonly double _weight;
}
readonly とすることで、読み取り専用のフィールドを宣言することができます。readonly フィールドは、宣言時かコンストラクタ内でのみ値を代入できるキーワードです。 結構お世話になるキーワードなので、頭の片隅にでも置いておくといいかもしれませんね。
プロパティ
クラスには "振る舞い" と "状態" の二つのメンバーがありますが、そのうちの "状態" は基本的に外部に公開しません。 しかし、時には状態を外部に見えるようにしたい場合が存在します。
そんなときに利用するのが、この "プロパティ" です。プロパティは外部に公開する際によく使われるため、public で宣言することがほとんどです。
クラスのプロパティ機能は強力ですが、その強力さ故に安易に使ってしまいがちです。ですが、本当に必要なとき以外にクラス外部へ状態を公開すべきではないため、 プロパティ機能を使う際には、本当に必要なのかどうか考えてから利用することが大切です。
プロパティは以下のように、クラス宣言内部にプロパティ宣言します。
class Hoge
{
// -------------------------------------------------------------
// プロパティはクラス宣言ブロックの内側で定義します。
//
// [ 宣言方法(1) ] 自動実装プロパティ
// <アクセス修飾子> 型名 プロパティ名
// {
// <アクセス修飾子> get;
// <アクセス修飾子> set;
// }
//
// [ 宣言方法(2) ] get, set が一行
// <アクセス修飾子> 型名 プロパティ名
// {
// <アクセス修飾子> get => フィールド名;
// <アクセス修飾子> set => フィールド名 = value;
// }
// private 型名 フィールド名;
//
// [ 宣言方法(3) ] get, set が複数行
// <アクセス修飾子> 型名 プロパティ名
// {
// <アクセス修飾子> get
// {
// // なんかの処理
// return フィールド名;
// }
// <アクセス修飾子> set
// {
// // なんらかの処理
// フィールド名 = value;
// }
// }
// private 型名 フィールド名;
//
// public の getter / setter を持つ、string型 の Name 静的プロパティを宣言
public static string Name{ get; set; }
// public の getter / setter を持つ、int型 の Number プロパティを宣言
// ただし、setter へのアクセスは private のみ
public int Number { get; private set; }
// public double型 の Weight プロパティを宣言
// Weight プロパティは _weight フィールドを公開するための入り口にすぎない
public int Weight
{
get => _weight;
set
{
if( 0 < value )
{ // 0 よりも大きい値のときのみ _weight に値を代入する
_weight = value;
}
}
}
private double _weight;
}
名前空間
今回のサンプル(Sample.cs)では、クラスが属する "名前空間 (namespace)" を宣言しています。 名前空間とは、同一名のクラスを分類するときなどに役立ちます(名前衝突の回避)。
自分ひとりで開発している分にはあまり問題になりませんが、他人が作ったライブラリなどを利用する場合に問題となりおます。 これは同一名のクラスを作成することができないことに起因しています。
とはいえ、もしこれを読んでくださっている方が初心者の方の場合、何を言っているのかわからないと思います。 もしそうであるならば、「クラスを分類するためのものなんだー」くらいに認識していればひとまずは大丈夫だと思います。
名前空間は以下のように宣言します。
namespace NamespaceName
{
// クラス定義を記述する
}
特別難しいものではありませんね。namespace の中に class を宣言すればよいだけです。