c# 基礎　その1

# C#とは
2000年に発表された*マルチパラダイム言語*。言語としてのパラダイムはオブジェクト指向が中心になっている。
>マルチパラダイム言語
 関数型・オブジェクト指向など多数のパラダイムに対応する言語。[(詳細)](https://www.weblio.jp/content/%E3%83%9E%E3%83%AB%E3%83%81%E3%83%91%E3%83%A9%E3%83%80%E3%82%A4%E3%83%A0%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9E)

# C#の特徴
.NET(.NET Framework)環境で動作する言語。
> **.NET**
様々な環境で動作する各種のライブラリや基盤となるフレームワークなども含めた統合開発環境。C言語などのマシン語に変換するコンパイルは、マシン語が固有のものであるため、環境によっては動作しないが、C#のコンパイルはマシン語ではなく**CIL(Common Intermediate Language : 共通中間言語)**として出力される。

.NET環境はそれぞれのプラットフォームに応じて提供されている。

|.NET|環境  |
|---|---|
|.NET Framework  |Windows|
|.NET Core|Linux・MacOSなど|
|Xamarin(Mono)|Android/iOSなど|

また、それぞれのプラットフォームでもライブラリを統一しようという試みを**.NET Standard**という。
>**オブジェクト指向**
プログラムで扱うモノをオブジェクトとして捉え、オブジェクトの組み合わせによって形成していく手法。

#変数
変数の種類は、大きく**値型**と**参照型**に分けられる。値型は実際を値を格納し、参照型の変数には値の格納場所を表すメモリ上のアドレスを格納する。

|型|種類|
|---|---|
|値型|int,charなど|
|参照型|クラス型,配列型など|
値型の実際の値や最小型のアドレスを格納するメモリ領域を**スタック**、参照型の実際のアドレスを格納するメモリ領域を**ヒープ**という。

**スタック**
OSやコンパイラが自動で確保するメモリ領域。サイズはプログラムがコンパイル等する時点で決まっている。
**ヒープ**
アプリケーションが必要なときに確保・解放する必要があるメモリ領域。サイズはメモリを確保するときに任意に指定することができる。

***浮動小数点型***
浮動小数点は**符号・指数・仮数**を繋げた値で管理している。

符号(1bit) 指数(8bit) 仮数(23bit)
符号 : 0(+),1(-)で表現される(1bit)
指数 : 指数にバイアス数(127)が足された値(8bit)
仮数 : 小数点以下の部分の値(23bit) ※ 整数部の1は固定なので不要

***文字型***
char型は文字として保持しているわけではなく、**Unicode(UTF-16)**に対応する値を保持している。
stringは文字型ではなく参照型(アドレスを格納)

***真偽型(論理型)***
true/falseで表記される型。コンソール出力では True/Falseと出るが、全て小文字でなければならないので注意。
また、他の言語のように 0や1を真偽に使うことはできない。

***オブジェクト型***
すべての型を代入できる。

```
object obj = 10;
obj = 'あ';
```

***型推論***
勝手に型を決めてくれるが、制約がいくつかある。
・初期値を省略できない。
・複数の変数をまとめて宣言できない。
・フィールド宣言では利用できない。(ローカル変数でなければ宣言できない)
・一度推論された型とは別の型の値を入れることはできない。
```
var 変数名 = 初期値;
```
#リテラル

|リテラル|表記例|
|---|---|
|10進数|-13,100|
|16進数|0xFF,0xA12C|
|2進数|0b1101,0b100|
|浮動小数点|1.4142e5,0.175E-5|
　※eは大文字でも小文字でも可、10進のみで使用可能。

***数値リテラル***
C#7以降では(_)で区切り記述できるようになった。((,)は別の意味を持つので使えない)
一般的には3桁ずつ区切る。
※123__456

以下でも問題ないが、先頭か末尾にセパレータがくるのはNG
12__34_____56
12____34

***文字リテラル***
シングルクォート(')で囲って表記する。 ※ 'あ','¥u3042'

***文字列リテラル***
ダブルクォート(")で囲って表記する。

***逐語的文字列リテラル***
@を使うことでエスケープ文字(¥)を使うことで無視して表記できる。(らしいが自分の環境では再現できず)

```
Console.WriteLine("¥¥100になります。");
Console.WriteLine(@"¥100になります。");
```

***文字列への変数展開***
$を使うことで{}内を式として判別できる。

```
string name = "山田";
Console.WriteLine($"こんにちは！{name}さん。");
Console.WriteLine($"2 + 3 は {2 + 3} です。");
```

#型変換
範囲の広い型から狭い型への型変換は基本可能。(***暗黙的型変換***)
狭い範囲への変換でも、**型キャスト**構文を利用してエラーを回避できる。(***明示的変換***)

```
int i = 3;
byte b = (byte)i;
```

数値型⇔文字列型

```
            Int32.Parse("108");
            Single.Parse("1.123");
            Int32.Parse("FF", System.Globalization.NumberStyles.HexNumber); // 255
            Double.Parse("0.123e2"); // 12.3
            Convert.ToInt32("1010", 2); // 10

            int i = 14;
            Console.WriteLine(i.ToString()); // 14
            Console.WriteLine(Convert.ToString(i,2)); // 1010
```

#参照型
大きく4種類に分類される。
・クラス型(組み込み型(stringなど)も含む)
・インターフェイス型
・デリゲート型
・配列型

***クラス型***
クラスに直接宣言された変数を***フィールド***といい、関数を***メソッド***という。これらを総称して***メンバー***という。
メンバ変数 = フィールド

クラスを元に生成することを***インスタンス化***といい、インスタンス化によってできるものをインスタンス(オブジェクト)という。

```
クラス名 変数名 = new クラス名(引数, ...)           // ()は省略できない。
```

クラスによってはインスタンス化しなくても呼び出せるものもある。このようなメソッドやフィールドを***クラスフィールド(静的フィールド)・クラスメソッド(静的フィールド)***という。
対して、オブジェクトを生成してから呼び出すフィールド・メソッドを***インスタンスフィールド・インスタンスメソッド***という。

クラスは 名前空間 + クラス名 の***完全修飾名***で表され、名前空間をのぞいたものを***単純名***という。またusingを使って単純名で表記できるようにすることを名前の解決という。


***null値***
参照をもたない特別な値として***null***がある。フィールドやメソッドを使おうとするとエラーになるので、以下のように(?)を使って回避することもできる。(C#6以降)

```
string s = null;
s?.Trim();
```
メソッド以外のプロパティやインデクサーも可能

```
obj?.length
obj[0]
```

***null許容型***
例えばint型の無効値が-1やMinValueなど使用者によってバラバラだったため、C#2から導入された機能。nullを代入できない値型にnullも代入できるようになる。

```
int i = 1;
int? j = null;
int k = null; // エラー
string? s = null; // 値型でないためエラー
Nullable<int> n; // int? n; と同義
```

***配列***

```
int[] data = new int[5];
int[] data2 = {1,2,3,4,5,}; // カンマで終わってもOK
int[] data3;
data3 =  new[]{1,2,3,4,5};
var data4 = new[]{1,2,3,4,5}; // int型
data4.length // 5;
data4[5] = 6; // ERROR
```

配列の要素数はnewした時点で固定される。要素数を増減させたい場合はListを使う。

***多次元配列***
多次元配列に対して、縦横の長さが不揃いな配列を**ジャグ配列**という。

```
int[,] data1 = new int[3,3];
int[,,] data2 = new int[3,3,3];

int[][] data3 = new int[3][];//
data3[0] = new int[2]; //
data3[1] = new int[4]; //ジャグ配列

```

多次元配列のlengthは配列内の要素数全体を返すが、ジャグ配列は配列自体の数を返すので注意(ジャグ配列は配列の要素として配列を持つことで多次元配列を実現しているため)