C# 言語のツアー

C# 言語は、無料のクロスプラットフォームのオープン ソース開発環境である .NET プラットフォームで最もよく使われている言語です。 C# プログラムは、モノのインターネット (IoT) デバイスからクラウド、そしてその間のあらゆる場所に至るまで、さまざまなデバイス上で実行できます。 電話、デスクトップ、ノート PC、サーバー用のアプリを作成できます。

C# は、高いパフォーマンスのコードを記述しながら開発者の生産性を向上させるクロスプラットフォームの汎用言語です。 何百万人もの開発者がいる C# は、最も人気のある .NET 言語です。 C# は、エコシステムとすべての .NET ワークロードを幅広くサポートしています。 オブジェクト指向の原則に基づいて、他のパラダイム (特に関数型プログラミング) の多くの機能が組み込まれています。 低レベルの機能は、安全でないコードを記述することなく、高効率のシナリオをサポートします。 .NET ランタイムとライブラリのほとんどは C# で記述されており、多くの場合、C# の進歩はすべての .NET 開発者に役立ちます。

Hello world

"Hello, World" は、プログラミング言語を紹介するために伝統的に使用されているプログラムです。 これを C# で記述すると次のようになります。

// This line prints "Hello, World" 
Console.WriteLine("Hello, World");

// で始まる行は、"単一行コメント" です。 C# の単一行コメントは、// で始まり、現在の行の終わりまで続きます。 C# では、"複数行コメント" もサポートされています。 複数行コメントは /* で始まり、*/ で終了します。 System 名前空間にある Console クラスの WriteLine メソッドは、プログラムの出力を生成します。 このクラスは標準クラス ライブラリによって提供され、既定ではすべての C# プログラムで自動的に参照されます。

前述の例は、最上位レベルのステートメントを使用した "Hello, World" プログラムの 1 つの形式を示しています。 以前のバージョンの C# では、メソッドでプログラムのエントリ ポイントを定義する必要があります。 この形式は引き続き有効であり、多くの既存の C# サンプルで見られます。 次の例に示すように、このフォームについても理解している必要があります。

using System;

class Hello
{
    static void Main()
    {
        // This line prints "Hello, World" 
        Console.WriteLine("Hello, World");
    }
}

このバージョンでは、プログラムで使用する構成要素が表示されます。 "Hello, World" プログラムは System 名前空間を参照する using ディレクティブで始まります。 名前空間は、C# のプログラムとライブラリを階層的に整理するための手段です。 名前空間には、型と他の名前空間が含まれます。たとえば、System 名前空間には多数の型 (プログラムで参照される Console クラスなど) と、他の多数の名前空間 (IOCollections など) が含まれます。 特定の名前空間を参照する using ディレクティブを使用すると、その名前空間のメンバーである型を修飾せずに使用できます。 using ディレクティブにより、プログラムで Console.WriteLineSystem.Console.WriteLine の省略形として使用できます。 前の例では、その名前空間が暗黙的に含まれていました。

"Hello, World" プログラムで宣言された Hello クラスにはメンバーが 1 つあります。Main という名前のメソッドです。 Main メソッドは static 修飾子を使用して宣言されています。 インスタンス メソッドが this で囲んだ特定のオブジェクト インスタンスを参照できるのに対し、静的メソッドは特定のオブジェクトを参照せずに機能します。 規則により、最上位レベルのステートメントがない場合、Main という名前の静的メソッドが C# プログラムのエントリ ポイントとして機能します。

どちらのエントリ ポイント フォームでも、同等のコードが生成されます。 最上位レベルのステートメントを使用すると、コンパイラによってプログラムのエントリ ポイントの包含クラスとメソッドが合成されます。

ヒント

この記事の例は、C# コードに初めて触れる機会を提供します。 一部のサンプルには、馴染みのない C# の要素が含まれている場合があります。 C# を学習する準備ができたら、初心者向けチュートリアルから始めるか、各セクションのリンクを参照してください。 JavaJavaScriptTypeScriptPython のいずれかの経験がある場合は、C# をすばやく学習するために必要な情報を見つけるのに役立つヒントをお読みください。

使い慣れた C# 機能

C# は初心者にも親しみやすく、専門的なアプリケーションを作成する経験豊富な開発者には高度な機能を提供します。 迅速に生産性を高めることができます。 アプリケーションに必要な、より専門的な手法を学習できます。

C# アプリは、.NET ランタイムの自動メモリ管理を利用できます。 C# アプリでは、.NET SDK によって提供される広範なランタイム ライブラリも使用されます。 ファイル システム ライブラリ、データ コレクション、数学ライブラリなど、一部のコンポーネントはプラットフォームに依存しません。 その他の ASP.NET Core Web ライブラリや .NET MAUI UI ライブラリなどは、単一のワークロードに固有のものもあります。 NuGet の豊富なオープン ソース エコシステムにより、ランタイムの一部であるライブラリが強化されます。 これらのライブラリでは、さらに多くのコンポーネントを使用できます。

C# は C ファミリの言語です。 C、C++、JavaScript、Java のいずれかを使用したことがある場合、C# 構文は馴染みのあるものです。 C ファミリのすべての言語と同様、セミコロン (;) によってステートメントの終了が定義されます。 C# 識別子では大文字と小文字が区別されます。 C# では、中かっこ {}ifelseswitch などの制御ステートメント、forwhile などのループ構造が同じように使われます。 C# には、任意のコレクション型に対する foreach ステートメントもあります。

C# は、"厳密に型指定された" 言語です。 宣言するすべての変数には、コンパイル時に既知の型があります。 その型を誤って使用しているかどうかが、コンパイラまたは編集ツールによって示されます。 プログラムを実行する前に、これらのエラーを修正できます。 基本データ型は、言語とランタイムに組み込まれています。intdoublechar などの値型、string、配列、その他のコレクションなどの参照型です。 プログラムを記述するときは、独自の型を作成します。 これらの型は、値の struct 型、またはオブジェクト指向の動作を定義する class 型です。 record 修飾子をstruct または class のいずれかの型に追加すると、コンパイラで等価比較用のコードを合成できるようになります。 また、そのインターフェイスを実装する型が提供する必要があるコントラクトまたはメンバーのセットを定義する interface 定義を作成することもできます。 ジェネリック型とメソッドを定義することもできます。 ジェネリックは "型パラメーター"を使用して、使用時に実際の型のプレースホルダーを提供します。

コードを記述するときは、関数 (メソッドとも呼ばれます) を struct 型および class 型のメンバーとして定義します。 これらのメソッドは、型の動作を定義します。 メソッドは、異なる数または型のパラメーターでオーバーロードできます。 メソッドは必要に応じて値を返すことができます。 メソッドに加えて、C# 型ではプロパティを持つことができます。これは、"アクセサー" と呼ばれる関数によってサポートされるデータ要素です。 C# 型ではイベントを定義できます。これにより、型は重要なアクションをサブスクライバーに通知できます。 C# では、class 型の継承やポリモーフィズムなどのオブジェクト指向の手法がサポートされています。

C# アプリでは、例外 を使用してエラーを報告および処理します。 C++ または Java を使用したことがある場合は、この方法に慣れているでしょう。 コードが意図したとおりに実行できない場合、例外がスローされます。 その他のコードは、呼び出し履歴のレベルに関係なく、必要に応じて try - catch ブロックを使用して回復できます。

C# の独特な機能

C# の一部の要素はあまり馴染みのないものかもしれません。 統合言語クエリ (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);
}

C# には、パターン マッチングが用意されています。 これらの式を使用すると、データを検査し、その特性に基づいて決定を行うことができます。 パターン マッチングは、データに基づく制御フローのための優れた構文を提供します。 次のコードは、ブール演算 andorxor のメソッドをパターン マッチング構文を使用して表現する方法を示しています。

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,
    };

最後に、Visual Studio または Visual Studio Code は、.NET エコシステムの一部として、C# DevKit とともに使用できます。 これらのツールは、記述するコードを含め、C# について豊富な理解を提供します。 また、デバッグ機能も提供します。