C#基礎文法最速マスター【令和2年版】

# 最初に

本記事は「令和時代の基礎文法最速マスター Advent Calendar 2020」にてC#での基礎文法をまとめて記載した記事となります。
初心者の方の役に立てれば幸いです。



まずは基本的なコードを確認してみましょう。



```c#
using System;

namespace Test
{
    public class HelloWorld
    {
        static void Main(string[] args)
        {
            string hello = "Hello 令和のC#！";
            Console.WriteLine(hello);
        }
    }
}
```



# 構文



## コメント

プログラムの処理に関係しない、プログラムに関する説明などを記載する場合には以下のように`//`もしくは`/**/`を使用してソースコード内にコメントを埋め込みます。

```
// 1文の場合

/*
    複数行のコメントの場合、このコメントで使用してる記号で囲むことでブロックコメントとなる。
*/
```





## メソッド

```c#
static void Main(string[] args)
```

プログラムはclass内の`Main`メソッドという特別なメソッドから始まります。

このメソッドは、アプリケーション起動時に必ず最初に呼び出されます。

`Main`メソッド内の`WriteLine()`もメソッドであり、引数として渡した文字列を表示します。

ユーザー側で定義する場合は基本的に以下のように書きます。

```C#
// アクセス修飾子 戻り値の型 関数名(引数の型 引数名)
// void は結果として特に返すものはない時に使用する
public void Attack()
{
	// 何かしらの処理
}

public bool IsDead()
{
	// キャラが死んでいるかどうかを返却
}

private void MoveForward(float AxisValue)
{
	// 前進する処理
}
```



## クラス

```C#
    public class HelloWorld
    {
        // メソッドや変数等
    }
```

プログラムの設計図の役割を持ちます。
![image-20201107214933816.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/2c422f41-15f0-9400-324b-82ac5db39417.png)


`public`や`protected`を用いて「継承」や「多態性」という機能を使用することができます。

classはcsファイル内に記述しますが、C#ではファイル名とクラス名は同一である必要性はありません。

また、１つのcsファイル内に複数の`class`を記述することも可能です。



## 型と変数

```c#
string hello = "Hello 令和のC#！";
```


![image-20201107215019582.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/3a335725-fd52-b01c-1477-df4e8e8699ed.png)


予めプログラミング言語側で用意されている「組み込み型」には以下のような種類があります。

```C#
// ------------値型------------
// データ型名　変数名
// int(整数)
int intNum = 2;

// float(単精度浮動小数点)
float floatNum = 1.234f;

// double(倍精度浮動小数点)
double doubleNum = 1.234;

// bool(論理)
// true か false 又は 1 か 0 です
bool boolVal = true;

// char(文字)
// ローマ字一文字を``で囲みます
char c = 'a';

// DateTime(日付)
DateTime date;


// ------------参照型------------

// String(文字列)
// 文字列を""で囲みます
String str = "hoge";

// 配列型
// 詳細は後述
int[] array;
```



また、先ほどのような自分で作成した`class`を基にした変数も使用可能です。
これを「ユーザー定義型」と呼びます。

```C#
public class HelloWorld
{
	public string Say()
	{
		return "Welcome C# World!";
	}
}

public class Hoge
{
	HelloWorld hello = new HelloWorld();
	string str = hello.Say();
}
```



## 四則演算

```C#
// num = 2
int num = 1 + 1;

// num2 = 0
int num2 = 1 - 1;

// num3 = 3
int num3 = 1 * 3;

// 小数点以下切り捨て
// num4 = 0
int num4 = 1 / 2;

// floatなので小数点が扱える
// num5 = 0.5
float num5 = 1 / 2;

// 余りの数の求め方
// num6 = 1
int num6 = 10 % 3;

// 複合代入演算子
// num = 2
num6 += 1;

// num = 1
num6 -= 1;
```



## インクリメント/デクリメント

`++`という、変数に対して`1`を足す専用の演算子が`インクリメント演算子`というものです。

主にループ処理などで使用されます。

`インクリメント演算子`には`前置インクリメント`と`後置インクリメント`があります。

違いは処理にする変数にて、1を足した後の結果を使用するか、足す前の値を使用するかで違いがあります。

```C#
using System;

class Test
{
	static void Main()
	{
		int i = 10;
		int k = 10;

        // 11が表示される
		Console.WriteLine(++i);
        // 10が表示される
		Console.WriteLine(k++);
        // 以降は k の値は11となっている
	}
}
```



また、変数に対して`1`を足す``インクリメント演算子`に対して、変数に対して`1`を引く`デクリメント演算子`というのも存在しています。

使い方は`インクリメント演算子`と変わりません。

```C#
using System;

class Test
{
	static void Main()
	{
		int i = 10;
		int k = 10;

        // 9が表示される
		Console.WriteLine(--i);
        // 10が表示される
		Console.WriteLine(k--);
        // 以降は k の値は9となっている
	}
}
```





## アクセス修飾子

```C#
public class HelloWorld
{
    // メソッドや変数等
}
```

アクセス修飾子は外部からその`class`やメソッド、変数を見たときに、使用できるか否かを決めます。

```C#
public class Character
{
    // 誰からも見えるし、誰でも使える
    public GetHP();
    public GetName();
    
    // このCharacterクラスの内部処理内でしか見えないし、使えない
    private void SetRotation();
}
```

他にも`protected`がありますが、こちらは継承の機能を使用する際に使います。



## 名前空間

```C#
namespace Test
{
	// HelloWorldクラス等
}
```

![image-20201107215126484.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/2cc3bed3-0ba1-07d0-8954-eac86e3b8b8d.png)


名前空間（`namespace`）とは、同じ名前が存在する（名前衝突）現象を防ぐ役割を持ちます。

例えば以下のように書くと名前の重複でエラーが起きます。

```C#
namespace ClassA
{
	public class Sato
	{
		// なにかしらの処理
	}
	
	public class Sato
	{
		// error!
	}
}
```

しかし`namespace`を使うことによって名前衝突を防ぐことができます。

![image-20201107215519686.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/e25d5e95-96cc-7641-593d-7e3313503dc9.png)


```C#
namespace ClassA
{
	public class Sato
	{
		public void Hello()
        {
            Console.WriteLine("My name is Sato! My class is A!");
		}
	}
}

namespace ClassB
{
	public class Sato
	{
            Console.WriteLine("My name is Sato! My class is B!");
	}
}
```

呼び出す時は名前空間付きで呼び出しましょう。

これを「完全修飾名」と言います。

```C#
namespace Test
{
    public class HelloWorld
    {
        static void Main(string[] args)
        {
        	ClassA.Sato sato = new ClassA.Sato();
            sato.Hello();
        }
    }
}
```



`using`というキーワードを使用することで、修飾名を省略して書くことができます。

この機能を`usingディレクティブ`と呼びます。

```C#
using ClassA;

namespace Test
{
    public class HelloWorld
    {
        static void Main(string[] args)
        {
        	Sato sato = new Sato();
            sato.Hello();
        }
    }
}
```



## 配列

```C#
// 型名[] 変数名;
string[] array;
```

配列の初期化には様々な方法があります。

```C#
// 普通の配列
// 変数 = new 型名[配列の長さ]
int array = new int[3];

// 配列の要素ごとに値を代入
array[0] = 5;
array[1] = 10;

// 初期データを指定 
int array2 = new int[] { 0, 5, 10 };
string[] cats = {"黒猫", "三毛猫", "ぶち", "はちわれ"};

// ジャグ配列での初期化
int[][] jagged = new int[][]
{
    new[] {1, 2, 3},
    new[] {4, 5, 6, 7}
};

// 四角配列での初期化
int[,] grid = new int[,]
{
    {1, 1, 1},
    {2, 2, 2},
    {3, 3, 3}
};
```



## if

条件分岐の処理を行う際に使用する構文です。

```C#
bool isDead = Hero.IsDead();

// もし勇者が死んでいたら
// if(isDead)でも可
if(isDead == true)
{
	// Gameover処理
}
else
{
	// 生きていたらClear処理
    // else if(isDead != true)　や
    // else if(!isDead)　とも書ける
}
```



## switchとenum

こちらも条件分岐などを行う際に使用すると便利な構文です。

enumとは`列挙型`と呼ばれる機能で、特定の値のみを取るようなものに対して使用します。

```C#
enum DayOfWeek
{
	Sunday,
	Monday,
	Tuesday,
	Wednesday,
	Thursday,
	Friday,
	Saturday
}
```



`switch`文は指定した変数の値によって処理を切り替えます。

```C#
DayOfWeek day = DayOfWeek.Monday;

switch(day)
{
	case DayOfWeek.Sunday:
		// おやすむ処理
		// breakが書かれることで処理を抜けます
		break;
	case DayOfWeek.Monday:
	case DayOfWeek.Tuesday:
	case DayOfWeek.Wednesday:
	case DayOfWeek.Thursday:
	case DayOfWeek.Friday:
		// 頑張ってお仕事するにゃんねぇの処理
		// caseにbreakを入れない場合は次のcaseの処理も続けて実行されます
		break;
	default:
		// defaultは変数の値がcaseで定義されている中のどれとも異なる場合に実行されます
		// 今回はSaturdayが対象です。
		break;
}
```



C#7.0からは以下のように型による分岐もできます。

```C#
switch (obj)
{
    case int n:
        // 整数だった場合の処理
        break;
    case string s:
        // 文字列だった場合の処理
        break;
    case bool b:
        // boolだった場合の処理
        break;
    default:
        // その他の場合の処理
        break;
}
```



## whileとfor

これはどちらもループ処理を行う際に使用する構文です。

まずはwhileから見てみましょう。

```C#
while(条件式)
{
	// ループ処理
}
```

例えば条件式の部分に`true`と書くとどこかで`break`を書かなくては無限ループとなります。

```C#
int i = 0;
while(i < 10)
{
	++i;
	// 何か処理
    
    if(i == 5)
    {
        // while文から抜ける
        break;
	}
}
```



次にfor文です。

こちらは、ループ処理に使用する変数の宣言・初期化と条件式、変数の値の更新をセットにして書くことができます。

```C#
for(初期化式; 条件式; 変数の更新式)
{
	// ループ処理
}
```

例えば、以下のように配列の要素を参照するときなどに使用できます。

```C#
int[] array = { 0, 5, 10 };
for(int i = 0; i < array.Length; i++)
{
    if(array[i] == 0)
    {
        // continueを書くとここでループ処理が中断され、変数の更新後ループ処理の頭から再度開始します
        continue;
	}
    
	array[i] += 10;
}

// arrayの中身は 0, 15, 20となる
```



## foreach

`foreach`を使うと、配列の各要素にアクセスして処理を行うのが楽になります。

```C#
int[] array = { 0, 5, 10 };

// foreach(変数宣言 in ループ処理したい配列)
foreach (int num in array)
{
    num += 10;
}
```





## 例外処理

例外を投げる場合には`throw`を使用します。

```C#
throw new Exception("not found!");
```

また、その例外を処理するには`try ~ catch`を使用します。

```C#
try
{
	// 例外が発生する可能性のある処理
}
catch(Exception e)
{
	// 例外に対応した処理
}
```



# 最後に

更に詳しくC#について知りたい方は以下のスライドを見てみてください～

https://speakerdeck.com/rossam/shi-te-wakaru-c-number-7-dot-1madefalseyan-yu-ji-neng

また、私の心の中で密かに師匠と崇めている岩永さんの技術ブログも非常におすすめです。

https://ufcpp.net/



それでは良きC#ライフを！