C# 言語は、無料のクロスプラットフォームのオープン ソース開発環境である .NET プラットフォームで最もよく使われている言語です。 C# プログラムは、モノのインターネット (IoT) デバイスからクラウド、そしてその間のあらゆる場所に至るまで、さまざまなデバイス上で実行できます。 電話、デスクトップ、ノート PC、サーバー用のアプリを作成できます。
C# は、高いパフォーマンスのコードを記述しながら開発者の生産性を向上させるクロスプラットフォームの汎用言語です。 何百万人もの開発者がいる C# は、最も人気のある .NET 言語です。 C# は、エコシステムとすべての .NET ワークロードを幅広くサポートしています。 オブジェクト指向の原則に基づいて、他のパラダイム (特に関数型プログラミング) の多くの機能が組み込まれています。 低レベルの機能は、安全でないコードを記述することなく、高効率のシナリオをサポートします。 .NET ランタイムとライブラリのほとんどは C# で記述されており、多くの場合、C# の進歩はすべての .NET 開発者に役立ちます。
C# は C ファミリの言語です。
C#構文 は、C、C++、JavaScript、TypeScript、または Java を使用した場合によく知られています。 C や C++ と同様に、セミコロン (;
) によってステートメントの末尾が定義されます。 C# 識別子では大文字と小文字が区別されます。 C# では、中かっこ {
と }
、if
、else
、switch
などの制御ステートメント、for
や while
などのループ構造が同じように使われます。 C# には、任意のコレクション型に対する foreach
ステートメントもあります。
ハローワールド
"Hello, World" は、プログラミング言語を紹介するために伝統的に使用されているプログラムです。 これを C# で記述すると次のようになります。
// This line prints "Hello, World"
Console.WriteLine("Hello, World");
//
で始まる行は、"単一行コメント" です。 C# の単一行コメントは、//
で始まり、現在の行の終わりまで続きます。 C# では、"複数行コメント" もサポートされています。 複数行コメントは /*
で始まり、*/
で終了します。
WriteLine
名前空間にある Console
クラスの System
メソッドは、プログラムの出力を生成します。 このクラスは標準クラス ライブラリによって提供され、既定ではすべての C# プログラムで自動的に参照されます。 別のプログラム フォームでは、プログラムのエントリ ポイントの包含クラスとメソッドを宣言する必要があります。 最上位レベルのステートメントを使用すると、コンパイラによってこれらの要素が合成されます。
この代替形式は引き続き有効であり、すべての C# プログラムの基本的な概念の多くが含まれています。 多くの既存の C# サンプルでは、次の同等の形式が使用されています。
using System;
namespace TourOfCsharp;
class Program
{
static void Main()
{
// This line prints "Hello, World"
Console.WriteLine("Hello, World");
}
}
上記の "Hello, World" プログラムは、using
名前空間を参照するSystem
ディレクティブで始まります。 名前空間は、C# のプログラムとライブラリを階層的に整理するための手段です。 名前空間には、型と他の名前空間が含まれます。たとえば、System
名前空間には多数の型 (プログラムで参照される Console
クラスなど) と、他の多数の名前空間 (IO
や Collections
など) が含まれます。 特定の名前空間を参照する using
ディレクティブを使用すると、その名前空間のメンバーである型を修飾せずに使用できます。
using
ディレクティブにより、プログラムで Console.WriteLine
を System.Console.WriteLine
の省略形として使用できます。 前の例では、その名前空間が暗黙的に含まれていました。
"Hello, World" プログラムで宣言された Program
クラスにはメンバーが 1 つあります。Main
という名前のメソッドです。
Main
メソッドは static
修飾子を使用して宣言されています。 インスタンス メソッドが this
で囲んだ特定のオブジェクト インスタンスを参照できるのに対し、静的メソッドは特定のオブジェクトを参照せずに機能します。 規則により、最上位レベルのステートメントがない場合、Main
という名前の静的メソッドが C# プログラムのエントリ ポイントとして機能します。
Main
メソッドを含むクラスは、通常、Program
という名前です。
ヒント
この記事の例は、C# コードに初めて触れる機会を提供します。 一部のサンプルでは、よく知らない C# の要素が示されている場合があります。 C# を学習する準備ができたら、初心者向けチュートリアルから始めるか、各セクションのリンクを参照してください。 Java、JavaScript、TypeScript、または Python の経験がある場合は、C# をすばやく学習するために必要な情報を見つけるのに役立つヒントをお読みください。
使い慣れた C# 機能
C# は初心者にも親しみやすく、専門的なアプリケーションを作成する経験豊富な開発者には高度な機能を提供します。 迅速に生産性を高めることができます。 アプリケーションに必要な、より専門的な手法を学習できます。
C# アプリは、.NET ランタイムの自動メモリ管理を利用できます。 C# アプリでは、.NET SDK によって提供される広範なランタイム ライブラリも使用されます。 ファイル システム ライブラリ、データ コレクション、数学ライブラリなど、一部のコンポーネントはプラットフォームに依存しません。 その他の ASP.NET Core Web ライブラリや .NET MAUI UI ライブラリなどは、単一のワークロードに固有のものもあります。 NuGet の豊富なオープン ソース エコシステムにより、ランタイムの一部であるライブラリが強化されます。 これらのライブラリでは、さらに多くのコンポーネントを使用できます。
C# は、"厳密に型指定された" 言語です。 宣言するすべての変数には、コンパイル時に既知の型があります。 その型を誤って使用しているかどうかが、コンパイラまたは編集ツールによって示されます。 プログラムを実行する前に、これらのエラーを修正できます。
基本データ型は、言語とランタイムに組み込まれています。int
、double
、char
などの値型、string
、配列、その他のコレクションなどの参照型です。 プログラムを記述するときは、独自の型を作成します。 これらの型は、値の struct
型、またはオブジェクト指向の動作を定義する class
型です。
record
修飾子をstruct
または class
のいずれかの型に追加すると、コンパイラで等価比較用のコードを合成できるようになります。 また、そのインターフェイスを実装する型が提供する必要があるコントラクトまたはメンバーのセットを定義する interface
定義を作成することもできます。 ジェネリック型とメソッドを定義することもできます。
ジェネリックは "型パラメーター"を使用して、使用時に実際の型のプレースホルダーを提供します。
コードを記述するときは、関数 (メソッドとも呼ばれます) を struct
型および class
型のメンバーとして定義します。 これらのメソッドは、型の動作を定義します。 メソッドは、異なる数または型のパラメーターでオーバーロードできます。 メソッドは必要に応じて値を返すことができます。 メソッドに加えて、C# 型ではプロパティを持つことができます。これは、"アクセサー" と呼ばれる関数によってサポートされるデータ要素です。 C# 型ではイベントを定義できます。これにより、型は重要なアクションをサブスクライバーに通知できます。 C# では、class
型の継承やポリモーフィズムなどのオブジェクト指向の手法がサポートされています。
C# アプリでは、例外 を使用してエラーを報告および処理します。 この方法は、C++ または Java を使用した場合によく知られています。 コードが意図したとおりに実行できない場合、例外がスローされます。 その他のコードは、呼び出し履歴のレベルに関係なく、必要に応じて try
- catch
ブロックを使用して回復できます。
C# の独特な機能
C# の一部の要素はあまり馴染みのないものかもしれません。
C# には、パターン マッチングが用意されています。 これらの式を使用すると、データを検査し、その特性に基づいて決定を行うことができます。 パターン マッチングは、データに基づく制御フローのための優れた構文を提供します。 次のコードは、ブール演算 and、or、xor のメソッドをパターン マッチング構文を使用して表現する方法を示しています。
public static bool Or(bool left, bool right) =>
(left, right) switch
{
(true, true) => true,
(true, false) => true,
(false, true) => true,
(false, false) => false,
};
public static bool And(bool left, bool right) =>
(left, right) switch
{
(true, true) => true,
(true, false) => false,
(false, true) => false,
(false, false) => false,
};
public static bool Xor(bool left, bool right) =>
(left, right) switch
{
(true, true) => false,
(true, false) => true,
(false, true) => true,
(false, false) => false,
};
パターン マッチング式は、_
を使用して任意の値のキャッチ オールとして簡略化できます。 次の例は、and メソッドを簡素化する方法を示しています。
public static bool ReducedAnd(bool left, bool right) =>
(left, right) switch
{
(true, true) => true,
(_, _) => false,
};
前の例では、 タプル、軽量データ構造も宣言しています。
タプルは、省略可能な名前と個々の型を持つ、順序付けされた固定長の値シーケンスです。 シーケンスは、 (
文字と )
文字で囲みます。 宣言 (left, right)
では、 left
と right
の 2 つのブール値を持つタプルを定義します。 各スイッチ アームは、 (true, true)
などのタプル値を宣言します。 タプルは、複数の値を持つ単一の値を宣言するための便利な構文を提供します。
コレクション式は、コレクション 値を提供するための一般的な構文を提供します。
[
文字と]
文字の間に値または式を記述すると、コンパイラはその式を必要なコレクション型に変換します。
int[] numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
List<string> names = ["Alice", "Bob", "Charlie", "David"];
IEnumerable<int> moreNumbers = [.. numbers, 11, 12, 13];
IEnumerable<string> empty = [];
前の例は、コレクション式を使用して初期化できるさまざまなコレクション型を示しています。 1 つの例では、 []
空のコレクション式を使用して、空のコレクションを宣言します。 別の例では、 ..
spread 要素 を使用してコレクションを展開し、その値をすべてコレクション式に追加します。
インデックス式と範囲式を使用して、インデックス可能なコレクションから 1 つ以上の要素を取得できます。
string second = names[1]; // 0-based index
string last = names[^1]; // ^1 is the last element
int[] smallNumbers = numbers[0..5]; // 0 to 4
^
インデックスは、先頭ではなく末尾から示します。
^0
要素はコレクションの末尾の 1 つ後にあるため、^1
は最後の要素です。 範囲式の ..
は、含める要素の範囲を表します。 範囲は最初のインデックスから始まり、最後のインデックスの要素は含まず、その手前までのすべての要素が含まれます。
統合言語クエリ (LINQ) は、データのコレクションをクエリまたは変換するための共通のパターン ベースの構文を提供します。 LINQ は、メモリ内コレクション、XML や JSON などの構造化データ、データベース ストレージ、さらにはクラウドベースのデータ API に対してクエリを実行するための構文を統合します。 1 セットの構文を学習すれば、ストレージに関係なくデータを検索および操作できるようになります。 次のクエリは、成績評価の平均値が 3.5 を超えるすべての学生を検索します。
var honorRoll = from student in Students
where student.GPA > 3.5
select student;
上記のクエリは、Students
で表される多くのストレージの種類に対して機能します。 これは、オブジェクトのコレクション、データベース テーブル、クラウド ストレージ BLOB、または XML 構造のいずれかです。 同じクエリ構文はすべてのストレージの種類に対して機能します。
タスクベースの非同期プログラミング モデルを使用すると、非同期で実行されているにもかかわらず、あたかも同期的に実行されているかのように読み取るコードを記述できます。
async
および await
のキーワードを使用して、非同期のメソッドと、式が非同期的に評価されるタイミングを記述します。 次の例では、非同期 Web 要求を待機します。 非同期操作が完了すると、メソッドは応答の長さを返します。
public static async Task<int> GetPageLengthAsync(string endpoint)
{
var client = new HttpClient();
var uri = new Uri(endpoint);
byte[] content = await client.GetByteArrayAsync(uri);
return content.Length;
}
C# では、GraphQL ページング API などの非同期操作によってサポートされるコレクションを反復処理する await foreach
ステートメントもサポートされています。 次のサンプルでは、データをチャンクで読み取り、利用可能な場合に各要素へのアクセスを提供する反復子を返します。
public static async IAsyncEnumerable<int> ReadSequence()
{
int index = 0;
while (index < 100)
{
int[] nextChunk = await GetNextChunk(index);
if (nextChunk.Length == 0)
{
yield break;
}
foreach (var item in nextChunk)
{
yield return item;
}
index++;
}
}
呼び出し元は、await foreach
ステートメントを使用してコレクションを反復処理できます。
await foreach (var number in ReadSequence())
{
Console.WriteLine(number);
}
最後に、Visual Studio または Visual Studio Code は、.NET エコシステムの一部として、C# DevKit とともに使用できます。 これらのツールは、記述するコードを含め、C# について豊富な理解を提供します。 また、デバッグ機能も提供します。
.NET