C# ドキュメント
簡潔で実例中心の C# リファレンス。概念を読み、コードを見て、Coddy のジャーニーで実践しましょう。
C# のガイド付き学習を始めるはじめに
- C#とはC#は、Microsoftが開発した静的型付けの汎用言語で、.NETの上で動きます。何に使われるのか、.NETとの関係、各バージョンで追加されたもの、そしてC#のプログラムの組み立て方を解説します。
- Hello World最初のC#のプログラムを1行ずつ解説します。Mainメソッド、Console.WriteLineとWrite、Console.ReadLineによる入力の読み取り、コメント、dotnet CLIによるプロジェクトの作成と実行、そしてトップレベルステートメントを扱います。
- C#とJavaの違いC#とJavaは見た目が似ていて、似た問題を解決します。本当の違いは、プロパティ、値型、ジェネリック、LINQとストリーム、非同期、例外、そしてそれらを取り巻くエコシステムにあります。コードを並べて比較します。
- C#とC++の違いC#はガベージコレクターを持つマネージド言語で、C++はネイティブコードにコンパイルされ、メモリを手動で制御できます。その違いが、安全性、性能、ゲームエンジン、ビルドの仕組み、それぞれの学びやすさにどう現れるかを解説します。
- 名前空間とusingC#の名前空間が型をどう整理し、usingディレクティブがそれをどうインポートするかを解説します。エイリアス、using static、完全修飾名、あいまいな参照の直し方、global using、ファイルスコープの名前空間を扱います。
基本
- 変数C#で変数を宣言して代入する方法、varを使うべきときと避けるべきとき、スコープの仕組み、const、readonly、static readonlyの違い、命名規則、そして未代入の変数のエラーを解説します。
- データ型C#のすべての組み込み型を、サイズ、範囲、リテラルの接尾辞とともに解説します。値型と参照型の違い、お金にdecimalを使う理由、整数のオーバーフローとchecked、既定値を扱います。
- 文字列からintへの変換C#で文字列をintに変換する方法をint.Parse、int.TryParse、Convert.ToInt32で解説します。暗黙と明示的なキャストの仕組み、doubleをキャストすると切り捨てられる理由、asとis演算子、そして"1.5"が15として解析されうる理由も扱います。
- 演算子C#の演算子を正確な動作とともに解説します。整数の除算、負の数に対する剰余演算子、インクリメントと複合代入、比較、短絡評価の論理演算、ビット演算子、null演算子、そして優先順位の表を扱います。
- 文字列C#の文字列の仕組みを解説します。不変性、Lengthとインデックス、==、Equals、string.Compareによる比較、エスケープ文字、逐語的な@文字列と複数行のテキスト、生文字列リテラル、nullと空のチェック、そして文字のループを扱います。
- SubstringC#のString.Substringの仕組みを解説します。開始インデックスと長さの引数、ArgumentOutOfRangeExceptionとその避け方、IndexOfの結果の前後のテキストの切り出し、最初や最後のn文字の取得、そしてC# 8の範囲演算子を扱います。
- 文字列補間C#の$"..."による文字列補間の仕組みを解説します。波かっこの中の式、F2、N0、C、D5、Xなどの書式指定子、表のための配置、波かっこのエスケープ、string.Formatと複合書式、逐語的な補間文字列と生の補間文字列、そして特定のカルチャでの書式設定を扱います。
- 文字列のメソッドC#で毎日使うStringのメソッドを解説します。複数の区切り文字とオプションを使うSplit、Replace、Containsと大文字小文字を区別しない検索、IndexOfとLastIndexOf、StartsWithとEndsWith、Trim、ToUpperとToLower、PadLeft、Join、Concat、そして文字列の反転を扱います。
- StringBuilderC#でループの中で文字列の連結を繰り返すと遅い理由と、StringBuilderがそれをどう解決するかを解説します。Append、AppendLine、AppendFormat、Insert、Remove、Replace、容量、そして普通の連結やstring.Joinのほうが適している場面を扱います。
- 乱数C#のRandomクラスで乱数を生成する方法を解説します。Nextとその上限を含まない範囲、範囲内のランダムなdouble、再現可能な結果のためのシード、ランダムな要素の選択、リストのシャッフル、ループの中のnew Randomの落とし穴、そして暗号的に安全な乱数を扱います。
- DateTimeC#で日付と時刻を扱う方法を解説します。DateTimeの値の作成、NowとUtcNowとToday、日数や月数の加算、減算によるTimeSpanの取得、TotalHoursとHours、日付の比較、DayOfWeek、ParseExactとTryParseによる解析、DateTimeOffset、DateOnlyを扱います。
- DateTimeの書式C#でDateTimeを文字列に書式設定する方法を解説します。標準の書式文字列(d、D、o、s、u、t)、yyyy-MM-dd HH:mm:ssのようなカスタムパターン、指定子の一覧表、カルチャによる出力の変化、"o"によるISO 8601のラウンドトリップ、そしてmmとMM、hhとHHの取り違えを扱います。
制御フロー
- if elseC#のif、else if、elseの動き方を解説します。条件がboolでなければならない理由、&&、||、!による条件の組み合わせ、波かっこが必要な場面、深いネストの代わりのガード節、そして=と==の取り違えや余計なセミコロンによるバグを扱います。
- switch文C#のswitch文の動き方を解説します。int、string、char、enumの値での分岐、すべてのcaseにbreakが必要な理由(エラーCS0163)、caseラベルを重ねて複数の値を扱う方法、goto case、default、文字列の大文字と小文字の区別、whenを使うパターンのcaseラベルを扱います。
- switch式C# 8のswitch式は、caseとbreakの代わりにパターンのアームで値を結果に変換します。構文、_ の破棄パターン、プロパティ、タプル、関係パターン、and/or/not、whenガード、網羅性の警告とSwitchExpressionExceptionを、実行できるC# 7の同等コードとともに解説します。
- 三項演算子C#の条件演算子 condition ? a : b は2つの値から1つを選びます。評価のされ方、両方の分岐に共通の型が必要な理由(CS0173)とそれを直すキャスト、三項演算子のネスト、文字列補間でのかっこ、そして ?? と ?. のほうが適している場面を解説します。
- for文C#のforループの動き方を解説します。初期化子、条件、反復子、逆順のカウントと増分の指定、複数のループ変数、インデックスによる配列のループ、ネストしたループ、for(;;)、そしてオフバイワンと反復中の削除によるバグを扱います。
- foreachループC#のforeachの動き方を解説します。配列、リスト、文字列、辞書(KeyValuePairと分解)のループ、インデックスの取得、ループ変数が読み取り専用である理由、「Collection was modified」のInvalidOperationExceptionとその対処、そしてforeachで使える型の条件を扱います。
- while文C#のwhileループとdo-whileループの動き方を解説します。本体の前か後で確認される条件、番兵や入力の終わりまでの読み込み、breakを使うwhile (true)、そしてつまずきやすい無限ループの間違いを扱います。
- breakとcontinueC#のbreak、continue、gotoの動き方を解説します。ループを早めに終える方法、反復を飛ばす方法、switchの中のbreak、多重ループから抜ける3つの方法(フラグ、goto、returnを使うメソッド)、そしてwhileの中のcontinueによる無限ループのバグを扱います。
メソッドとデリゲート
- メソッドC#でメソッドを宣言して呼び出す方法を解説します。戻り値の型とvoid、引数、式形式のメソッド、タプルで複数の値を返す方法、オーバーロード、params配列、静的メソッドとインスタンスメソッド、Mainメソッド、再帰、ローカル関数を扱います。
- 省略可能な引数C#の省略可能な引数と名前付き引数の仕組みを解説します。既定値とコンパイル時定数のルール、引数の順序、名前による引数の省略、省略可能な引数とオーバーロードの比較、呼び出し元情報の属性、そして呼び出し側に埋め込まれる既定値によるバージョン管理の落とし穴を扱います。
- refとoutC#のref、out、in引数の仕組みを解説します。コピーではなく変数そのものを渡す方法、追加の結果を返すoutとTryParseパターン、out var、読み取り専用のin引数、確実な代入のルール、そして引数が参照型のときに何が変わるかを扱います。
- ラムダ式C#のラムダ式の仕組みを解説します。=>構文のあらゆる形、FuncとActionへのラムダの格納、メソッドやLINQへの受け渡し、ステートメント形式のラムダ、キャプチャした変数に対するクロージャ、そしてforeachにはないforループのキャプチャのバグを扱います。
- デリゲートC#のデリゲートとは何か、どう使うかを解説します。デリゲート型の宣言、メソッド、ラムダ、匿名メソッドからの作成、呼び出し、コールバックとしてのデリゲート、+=と-=によるマルチキャストデリゲート、?.Invokeによるnullチェック、そしてFunc、Action、イベントとの関係を扱います。
- FuncとActionC#のFuncとActionの仕組みを解説します。値を返す関数のためのFunc<T, TResult>、値を返さない関数のためのAction<T>、PredicateとComparison、関数の受け渡しと返却、コマンドの辞書、非同期のラムダ、そして独自のデリゲートを宣言すべき場面を扱います。
- イベントC#のイベントの仕組みを解説します。EventHandlerとEventHandler<T>によるイベントの宣言、独自のEventArgsクラス、+=と-=による購読と解除、?.Invokeによる安全なイベントの発生、publicなデリゲートのフィールドよりイベントが優れている理由、そして解除し忘れによるメモリリークを扱います。
- 拡張メソッドC#の拡張メソッドの仕組みを解説します。最初の引数にthisを付けた静的クラスの静的メソッド、インスタンスメソッドのような呼び出し、string、enum、IEnumerable<T>の拡張、拡張メソッドで作られたLINQ、インスタンスメソッドが優先される理由、nullのレシーバー、そして必要なusingディレクティブを扱います。
コレクションとLINQ
- 配列C#の配列は、1つの型の要素を固定の数だけ持つブロックです。配列の宣言と初期化、Lengthの読み取り、Arrayクラスによるソートと検索、安全なコピー、そして2次元配列とジャグ配列の扱い方を学びます。
- ListList<T>はC#の伸縮する配列です。リストの作成、要素の追加と挿入、値、インデックス、条件による削除、ContainsとFindによる検索、プロパティによる並べ替え、そしてforeachの中でリストを変更したときのエラーの避け方を学びます。
- DictionaryDictionary<TKey, TValue>はキーを値に対応付け、高速に検索できます。エントリの追加と更新、TryGetValueによる安全な読み取り、KeyValuePairのループ、出現回数の集計、大文字と小文字を区別しないキー、SortedDictionaryによるキーのソートを学びます。
- HashSetHashSet<T>は一意な要素を保持し、Containsに定数時間で答えます。Addが重複をどう報告するか、リストから重複を取り除く方法、集合の和、積、差の求め方、そして自分で作ったオブジェクトを値で比較させる方法を学びます。
- QueueQueue<T>は先入れ先出しのコレクションで、要素は到着した順に出ていきます。Enqueue、Dequeue、Peek、空のキューの例外とTryDequeue、キューを使った幅優先探索、そしてConcurrentQueueやPriorityQueueを使うべき場面を学びます。
- StackStack<T>は後入れ先出しのコレクションで、最後に追加した要素が最初に出てきます。Push、Pop、Peek、空のスタックの例外とTryPop、スタックが逆順に列挙される理由、そして2つの典型的な用途である元に戻す履歴とかっこの対応チェックを学びます。
- タプルC#のタプルは、型を宣言せずに少数の値を1つにまとめます。値タプルの構文、名前付きの要素、メソッドから複数の値を返す方法、var (a, b) による分解、辞書のキーとしてのタプル、そしてValueTupleと古いSystem.Tupleの違いを学びます。
- LINQLINQはC#のすべてのコレクションにクエリ演算子を加えます。メソッド構文とクエリ構文、Whereによる絞り込み、Selectによる射影、OrderByとThenByによる並べ替え、GroupByによるグループ化、FirstとFirstOrDefaultの落とし穴、集計、そして遅延実行によってクエリが実行されるタイミングがどう変わるかを学びます。
- IEnumerableとyieldIEnumerable<T>はforeachとLINQを支えるインターフェースで、yield returnはそれを実装する最も簡単な方法です。IEnumerableとICollectionやListの関係、イテレーターメソッドが一歩ずつ実行される仕組み、yield break、無限シーケンス、そして遅延評価の落とし穴を学びます。
クラスと型
- クラスとオブジェクトC#でクラスを宣言し、フィールドとメソッドを持たせ、newでオブジェクトを作る方法、そしてクラスが参照型であることの意味を解説します。共有されるオブジェクト、nullとNullReferenceException、ToString、オブジェクト初期化子を扱います。
- コンストラクターC#のコンストラクターの仕組みを解説します。暗黙の既定のコンストラクターと、それが消える場合、引数付きとオーバーロードされたコンストラクター、this(...)とbase(...)による連鎖、実行される順序、静的とprivateなコンストラクター、そしてC# 12のプライマリコンストラクターを扱います。
- プロパティC#のプロパティの仕組みを解説します。バッキングフィールドに対するgetとsetのアクセサー、自動実装プロパティ、private setと読み取り専用のプロパティ、計算されるプロパティ、setterでの検証、そしてC# 9と11のinitとrequiredキーワードを扱います。
- staticキーワードC#のstaticの意味を解説します。オブジェクトではなく型に属するメンバー、インスタンス間で共有される状態、静的メソッドと静的クラス、静的コンストラクター、constとstatic readonlyの違い、using static、そしてCS0120のエラーを扱います。
- アクセス修飾子C#の6つのアクセス修飾子(public、private、protected、internal、protected internal、private protected)、それぞれが何を許すか、何も書かない場合の既定、そしてそれらが生むコンパイルエラーを解説します。
- 継承C#のクラスの継承の仕組みを解説します。コロンによる派生、継承されるものとされないもの、baseによる基底クラスの呼び出し、virtualとoverride、newによる隠蔽(と誰もが驚く出力)、sealed、ポリモーフィズム、そして階層の上下へのキャストを扱います。
- 抽象クラスC#の抽象クラスとは何かを解説します。インスタンス化できず、派生クラスが実装しなければならない抽象メンバーを宣言できる基底クラスです。抽象メソッドと抽象プロパティ、コンストラクター、テンプレートメソッドパターン、そして代わりにインターフェースを選ぶべき場面を扱います。
- インターフェースC#のインターフェースの仕組みを解説します。宣言、クラスと構造体での実装、型としてのインターフェースの使用、複数の同時実装、明示的な実装、最もよく実装するフレームワークのインターフェース(IComparable<T>、IEnumerable<T>、IDisposable)、そしてC# 8の既定のインターフェースメソッドを扱います。
- 構造体C#の構造体の仕組みを解説します。値のセマンティクスと代入時のコピー、List<T>の変更エラー、コンストラクターのルール、等価性、ボックス化、readonly structとrecord struct、そして構造体が適している場面の指針とともに構造体とクラスを比較します。
- enum(列挙型)C#のenumの仕組みを解説します。名前付き定数の宣言、基になる整数値とキャスト、enumから文字列、ParseとTryParseによる文字列からenumへの変換、すべての値の一覧、ビット演算子とHasFlagを使う[Flags]、enumでのswitch、そして定義されていない値の扱いを扱います。
- レコードC#のレコード(C# 9以降)とは何かを解説します。位置指定の構文、コンパイラが生成するメンバー、値に基づく等価性、withによる非破壊的なコピー、組み込みのToString、C# 10のrecord struct、レコード間の継承、そして手書きした同等のクラスを扱います。
- ジェネリックC#のジェネリックの仕組みを解説します。型パラメーターを使うジェネリッククラスとメソッドの書き方、型推論、where(class、struct、new()、基底クラス、インターフェース)による制約、default(T)、型ごとの静的メンバー、そしてIEnumerable<out T>による共変性を扱います。
- null許容型C#のnullのすべてを解説します。HasValue、Value、GetValueOrDefaultを持つnull許容値型(int?、Nullable<T>)、null合体演算子??と??=、null条件演算子?.、nullチェック、そしてC# 8のnull許容参照型(string?)を扱います。
- パターンマッチングC#のパターンマッチングの仕組みを解説します。型パターンと定数パターンを使うis演算子、caseのパターンとwhenを使うswitch文、switch式、プロパティ、タプル、位置指定のパターン、関係パターンと論理パターン(and、or、not)、リストパターン、そしてそれぞれを追加したC#のバージョンを扱います。
例外
- try catchtry、catch、finallyはC#で例外を処理する仕組みです。例外が呼び出し履歴をさかのぼる流れ、特定の例外の型を正しい順序でキャッチする方法、whenによるフィルター、finallyでの後片付け、スタックトレースを失わないthrow;による再スロー、そしてキャッチすべきでない例外を学びます。
- 例外を投げるC#でいつ、どのように例外を投げるかを解説します。throw文、どの組み込みの例外型がどの間違いに合うか、??と?:によるthrow式、ThrowIfNullのヘルパー、そして独自のデータと内部例外を持つ独自の例外クラスの書き方を学びます。
- usingステートメントusingステートメントは、例外が投げられた場合でも、ファイル、ストリーム、接続などのIDisposableなオブジェクトでDisposeが呼ばれることを保証します。それが何にコンパイルされるか、オブジェクトが破棄される順序、C# 8のusing宣言、そして自分のクラスでIDisposableを実装する方法を学びます。
非同期とスレッド
- async/awaitasyncとawaitを使うと、C#のコードはスレッドをブロックせずに遅い処理を待てます。asyncメソッドの実行のされ方、TaskとTask<T>、Task.WhenAllで独立した処理を同時に実行する方法、非同期コードの例外、そしてasync voidと.Resultがバグやデッドロックを起こす理由を学びます。
- TaskTaskは.NETにおける非同期処理と並列処理の単位です。CPUバウンドの処理のためのTask.Run、結果の読み取り、WhenAllとWhenAnyによるタスクの組み合わせ、継続、CancellationTokenによるキャンセル、TaskとThreadの違い、そしてParallel.Forのほうが適している場面を学びます。
- lockステートメントlockステートメントは、一度に1つのスレッドだけがコードのブロックを実行できるようにします。競合状態がカウンターを壊す様子を確認し、lockで直し、どのオブジェクトでロックすべきかを学び、単純なカウンターにはInterlockedを使い、ロックの順序によるデッドロックを避け、中でawaitするコードにはSemaphoreSlimを使います。
- タイマーC#にはいくつかのタイマークラスがあり、それぞれ動作が異なります。System.Threading.Timer、System.Timers.Timer、PeriodicTimer、UIのタイマーを使い分ける方法、開始と停止、コールバックがスレッドプールで実行されて重なりうる理由、タイマーへの参照を保持しなければならない理由、そしてStopwatchで経過時間を測る方法を学びます。
ファイル、JSONなど
- ファイルの読み書きC#でファイルに書き込み、ファイルを読み込む方法を解説します。ファイル全体を扱うFile.WriteAllText、ReadAllText、AppendAllText、WriteAllLines、ReadAllLines、大きなファイルのためのStreamWriterとStreamReader、Path.Combineによるパス、ディレクトリ、エンコーディング、そしてファイルを扱うコードが処理すべき例外を扱います。
- JSONC#でSystem.Text.Jsonを使ってJSONを扱う方法を解説します。JsonSerializer.SerializeとDeserialize、camelCaseとインデント付きの出力、JsonPropertyNameやJsonIgnoreなどの属性、文字列としてのenum、JsonDocumentとJsonNodeによるクラスなしのJSONの読み取り、エラー、そしてNewtonsoft.Jsonとの比較を扱います。
- 正規表現C#でSystem.Text.RegularExpressionsを使って正規表現を扱う方法を解説します。IsMatch、MatchとMatches、番号付きと名前付きのグループ、置換パターンとラムダを使うReplace、Split、RegexOptions、逐語的なパターン文字列、入力の検証、タイムアウト、そして.NET 7のGeneratedRegex属性を扱います。
- リフレクションと属性C#のリフレクションの仕組みを解説します。typeofとGetTypeによるTypeオブジェクト、プロパティの読み取りと設定、名前によるメソッドの呼び出し、インスタンスの作成、そして属性(Obsoleteなどの組み込みのもの、独自の属性の宣言、実行時の読み取り)を扱います。リフレクションのコストも説明します。