C# 言語のツアーA tour of the C# language

C# ("シー シャープ" と読みます) は、最新のタイプ セーフなオブジェクト指向のプログラミング言語です。C# (pronounced "See Sharp") is a modern, object-oriented, and type-safe programming language. C# は C 言語ファミリーをルーツとしているため、C、C++、Java、JavaScript のプログラマーであればすぐに使いこなすことができます。C# has its roots in the C family of languages and will be immediately familiar to C, C++, Java, and JavaScript programmers. このツアーでは、C# 8 以前の言語の主要なコンポーネントの概要について説明します。This tour provides an overview of the major components of the language in C# 8 and earlier. 対話型の例を通して言語を調べたい場合は、C# の概要に関するチュートリアルを参照してください。If you want to explore the language through interactive examples, try the introduction to C# tutorials.

C# は、オブジェクト指向、"コンポーネント指向" のプログラミング言語です。C# is an object-oriented, component-oriented programming language. C# はこれらの概念を直接サポートする言語コンストラクトを提供しているので、自然にソフトウェア コンポーネントを作成して使用することができます。C# provides language constructs to directly support these concepts, making C# a natural language in which to create and use software components. 当初から、C# では、新しいワークロードと新しいソフトウェア設計プラクティスをサポートする機能が追加されています。Since its origin, C# has added features to support new workloads and emerging software design practices.

C# には、堅牢で永続的なアプリケーションの構築を支援するさまざまな機能が用意されています。Several C# features aid in the construction of robust and durable applications. "ガベージ コレクション" は、到達できず、使用されていないオブジェクトによって占有されたメモリを自動的に解放します。Garbage collection automatically reclaims memory occupied by unreachable unused objects. "例外処理" は、エラーの検出と復旧を行うための構造化された拡張可能なアプローチを提供します。Exception handling provides a structured and extensible approach to error detection and recovery. "ラムダ式" は、関数型プログラミング手法をサポートします。Lambda expressions support functional programming techniques. "クエリ構文" では、任意のソースからのデータを操作するための一般的なパターンが作成されます。Query syntax creates a common pattern for working with data from any source. "非同期操作" の言語サポートでは、分散システムを構築するための構文が提供されます。Language support for asynchronous operations provides syntax for building distributed systems. "パターン マッチング" には、最新の分散システムのアルゴリズムからのデータを簡単に分割するための構文が用意されています。Pattern matching provides syntax to easily separate data from algorithms in modern distributed systems. C# は "統合型システム" を採用しています。C# has a unified type system. intdouble などのプリミティブ型を含めた C# のすべての型は、ルートとなる 1 つの object 型から派生しています。All C# types, including primitive types such as int and double, inherit from a single root object type. すべての型は、一般的な操作のセットを共有します。All types share a set of common operations. すべての型の値を一貫した方法で格納、転送、操作することができます。Values of any type can be stored, transported, and operated upon in a consistent manner. さらに、C# では、ユーザー定義の参照型と値型の両方がサポートされています。Furthermore, C# supports both user-defined reference types and value types. C# では、オブジェクトを動的に割り当てたり、軽量の構造体をインラインで格納したりすることもできます。C# allows dynamic allocation of objects and in-line storage of lightweight structures.

C# では、プログラムとライブラリが互換性を保ちながら時間とともに進化できるように、"バージョン管理" に重点が置かれています。C# emphasizes versioning to ensure programs and libraries can evolve over time in a compatible manner. C# の設計でバージョン管理の考慮の影響を直接受けている側面として、別個の virtual 修飾子と override 修飾子、メソッドのオーバーロードの解決規則、明示的なインターフェイス メンバー宣言のサポートなどがあります。Aspects of C#'s design that were directly influenced by versioning considerations include the separate virtual and override modifiers, the rules for method overload resolution, and support for explicit interface member declarations.

Hello worldHello world

"Hello, World" は、プログラミング言語を紹介するために伝統的に使用されているプログラムです。The "Hello, World" program is traditionally used to introduce a programming language. これを C# で記述すると次のようになります。Here it is in C#:

using System;

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

"Hello, World" プログラムは System 名前空間を参照する using ディレクティブで始まります。The "Hello, World" program starts with a using directive that references the System namespace. 名前空間は、C# のプログラムとライブラリを階層的に整理するための手段です。Namespaces provide a hierarchical means of organizing C# programs and libraries. 名前空間には、型と他の名前空間が含まれます。たとえば、System 名前空間には多数の型 (プログラムで参照される Console クラスなど) と、他の多数の名前空間 (IOCollections など) が含まれます。Namespaces contain types and other namespaces—for example, the System namespace contains a number of types, such as the Console class referenced in the program, and a number of other namespaces, such as IO and Collections. 特定の名前空間を参照する using ディレクティブを使用すると、その名前空間のメンバーである型を修飾せずに使用できます。A using directive that references a given namespace enables unqualified use of the types that are members of that namespace. using ディレクティブにより、プログラムで Console.WriteLineSystem.Console.WriteLine の省略形として使用できます。Because of the using directive, the program can use Console.WriteLine as shorthand for System.Console.WriteLine.

"Hello, World" プログラムで宣言された Hello クラスにはメンバーが 1 つあります。Main という名前のメソッドです。The Hello class declared by the "Hello, World" program has a single member, the method named Main. Main メソッドは static 修飾子を使用して宣言されています。The Main method is declared with the static modifier. インスタンス メソッドが this で囲んだ特定のオブジェクト インスタンスを参照できるのに対し、静的メソッドは特定のオブジェクトを参照せずに機能します。While instance methods can reference a particular enclosing object instance using the keyword this, static methods operate without reference to a particular object. 規則により、Main という名前の静的メソッドは C# プログラムのエントリ ポイントとして使用されます。By convention, a static method named Main serves as the entry point of a C# program.

プログラムの出力は、System 名前空間にある Console クラスの WriteLine メソッドによって生成されます。The output of the program is produced by the WriteLine method of the Console class in the System namespace. このクラスは、コンパイラによって自動的に参照される、標準のクラス ライブラリで提供されています。This class is provided by the standard class libraries, which, by default, are automatically referenced by the compiler.

型と変数Types and variables

C# には、値型参照型という 2 種類の型があります。There are two kinds of types in C#: value types and reference types. 値型の変数が直接データを格納するのに対して、参照型の変数はデータへの参照を格納し、後者はオブジェクトとして知られています。Variables of value types directly contain their data whereas variables of reference types store references to their data, the latter being known as objects. 参照型を使用すると 2 つの変数が同じオブジェクトを参照でき、1 つの変数に対する演算によって、もう一方の変数によって参照されるオブジェクトに影響を与えることができます。With reference types, it's possible for two variables to reference the same object and possible for operations on one variable to affect the object referenced by the other variable. 値型の場合、各変数によって独自のデータ コピーが保持され、1 つの変数に対する演算によって別の変数に影響を与えることはできません (refout のパラメーターの変数を除く)。With value types, the variables each have their own copy of the data, and it isn't possible for operations on one to affect the other (except for ref and out parameter variables).

"識別子" は変数名です。An identifier is a variable name. 識別子は、空白を含まない unicode 文字のシーケンスです。An identifier is a sequence of unicode characters without any whitespace. 先頭に @ が指定されている場合、識別子は C# の予約語になります。An identifier may be a C# reserved word, if it is prefixed by @. これは、他の言語と対話するときに便利です。That can be useful when interacting with other languages.

C# の値の型はさらに、"単純型"、"列挙型"、"構造体型"、"null 許容値型"、および "タプル値型" に分けられます。C#'s value types are further divided into simple types, enum types, struct types, nullable value types and tuple value types. C# の参照型はさらに、"クラス型"、"インターフェイス型"、"配列型"、および "デリゲート型" に分けられます。C#'s reference types are further divided into class types, interface types, array types, and delegate types.

以下は、C# の型システムの概要です。The following outline provides an overview of C#'s type system.

C# プログラムでは型宣言を使用して新しい型を作成します。C# programs use type declarations to create new types. 型宣言は、新しい型の名前とメンバーを指定します。A type declaration specifies the name and the members of the new type. C# の型カテゴリのうち 6 つはユーザー定義が可能です。クラス型、構造体型、インターフェイス型、列挙型、デリゲート型、およびタプル値型です。Six of C#'s categories of types are user-definable: class types, struct types, interface types, enum types, delegate types and tuple value types.

  • class 型は、データ メンバー (フィールド) と関数メンバー (メソッド、プロパティ、その他) を含むデータ構造を定義します。A class type defines a data structure that contains data members (fields) and function members (methods, properties, and others). クラス型では、単一継承とポリモーフィズムをサポートします。このメカニズムによって派生クラスが基底クラスを拡張して特殊化できます。Class types support single inheritance and polymorphism, mechanisms whereby derived classes can extend and specialize base classes.
  • struct 型は、データ メンバーおよび関数メンバーで構造体を表す点において、クラス型に似ています。A struct type is similar to a class type in that it represents a structure with data members and function members. ただしクラスと異なり、構造体は値型で、通常はヒープ割り当てが不要です。However, unlike classes, structs are value types and don't typically require heap allocation. 構造体型ではユーザー指定の継承がサポートされず、すべての構造体型によって暗黙的に object 型が継承されます。Struct types don't support user-specified inheritance, and all struct types implicitly inherit from type object.
  • interface 型では、パブリック メンバーの名前付きセットとしてコントラクトが定義されます。An interface type defines a contract as a named set of public members. interface を実装する class または struct は、インターフェイスのメンバーの実装を提供する必要があります。A class or struct that implements an interface must provide implementations of the interface's members. interface は複数の基底インターフェイスから継承することがあり、class または struct は複数のインターフェイスを実装することがあります。An interface may inherit from multiple base interfaces, and a class or struct may implement multiple interfaces.
  • delegate 型は、特定のパラメーター リストおよび戻り値を使用してメソッドへの参照を表します。A delegate type represents references to methods with a particular parameter list and return type. デリゲートを使用すると、変数に割り当ててパラメーターとして渡すことのできるエンティティとして、メソッドを処理できます。Delegates make it possible to treat methods as entities that can be assigned to variables and passed as parameters. デリゲートは、関数型言語で提供される関数の型に似ています。Delegates are analogous to function types provided by functional languages. また、他のいくつかの言語で見られる関数ポインターの概念に似ています。They're also similar to the concept of function pointers found in some other languages. ただし、関数ポインターとは異なり、デリゲートはオブジェクト指向で、タイプ セーフです。Unlike function pointers, delegates are object-oriented and type-safe.

classstructinterface および delegate の型はすべてジェネリックをサポートし、他の型と共にパラメーター化できます。The class, struct, interface, and delegate types all support generics, whereby they can be parameterized with other types.

C# では、あらゆる型の 1 次元および多次元の配列がサポートされています。C# supports single-dimensional and multi-dimensional arrays of any type. 上記の型とは異なり、配列型は使用前に宣言する必要がありません。Unlike the types listed above, array types don't have to be declared before they can be used. 代わりに配列型は、角かっこで囲んだ型名を後に付けることにより構成されます。Instead, array types are constructed by following a type name with square brackets. たとえば、int[]int の 1 次元配列、int[,]int の 2 次元配列、int[][]int の 1 次元配列の 1 次元配列、または "ジャグ" 配列です。For example, int[] is a single-dimensional array of int, int[,] is a two-dimensional array of int, and int[][] is a single-dimensional array of single-dimensional arrays, or a "jagged" array, of int.

null 許容型は個別の定義を必要としません。Nullable types don't require a separate definition. null 非許容型 T のそれぞれについて、対応する null 許容型 T? があり、これは追加値 null を保持することができます。For each non-nullable type T, there's a corresponding nullable type T?, which can hold an additional value, null. たとえば、int? は 32 ビット整数または値 null を保持できる型であり、string?string または値 null を保持できる型です。For instance, int? is a type that can hold any 32-bit integer or the value null, and string? is a type that can hold any string or the value null.

C# の型システムは、任意の型の値を object として扱えるように統一されています。C#'s type system is unified such that a value of any type can be treated as an object. C# における型はすべて、直接的または間接的に object クラス型から派生し、object はすべての型の究極の基底クラスです。Every type in C# directly or indirectly derives from the object class type, and object is the ultimate base class of all types. 参照型の値は、値を単純に object 型としてみなすことによってオブジェクトとして扱われます。Values of reference types are treated as objects simply by viewing the values as type object. 値型の値は、ボックス化ボックス化解除操作を実行することによって、オブジェクトとして扱われます。Values of value types are treated as objects by performing boxing and unboxing operations. 次の例では、int 値は object 値に変換され、また int に戻されます。In the following example, an int value is converted to object and back again to int.

int i = 123;
object o = i;    // Boxing
int j = (int)o;  // Unboxing

値型の値が object 参照に割り当てられている場合は、値を保持するために "ボックス" が割り当てられます。When a value of a value type is assigned to an object reference, a "box" is allocated to hold the value. このボックスは参照型のインスタンスであり、そのボックスに値がコピーされます。That box is an instance of a reference type, and the value is copied into that box. 逆に、object 参照が値型にキャストされると、参照先の object が適切な値型のボックスかどうかが確認されます。Conversely, when an object reference is cast to a value type, a check is made that the referenced object is a box of the correct value type. 確認が成功すると、ボックス内の値が値型にコピーされます。If the check succeeds, the value in the box is copied to the value type.

C# の型システムが統一されたということは、実質的には値型が "オンデマンドで" object 参照として扱われるということです。C#'s unified type system effectively means that value types are treated as object references "on demand." こうした統一性があるため、object 型を使用する汎用的なライブラリは、参照型と値型の両方を含め、object から派生するすべての型で使用できます。Because of the unification, general-purpose libraries that use type object can be used with all types that derive from object, including both reference types and value types.

C# には、フィールド、配列要素、ローカル変数、パラメーターなどの、いくつかの種類の変数があります。There are several kinds of variables in C#, including fields, array elements, local variables, and parameters. 変数は格納場所を表します。Variables represent storage locations. 各変数には型があり、次のように、この型によって変数に格納できる値が決まります。Every variable has a type that determines what values can be stored in the variable, as shown below.

  • null 非許容値型Non-nullable value type
    • 型そのものの値A value of that exact type
  • null 許容値型Nullable value type
    • null 値、またはその型そのものの値A null value or a value of that exact type
  • objectobject
    • null 参照、任意の参照型のオブジェクトへの参照、または任意の値型のボックス化された値への参照A null reference, a reference to an object of any reference type, or a reference to a boxed value of any value type
  • クラス型Class type
    • null 参照、そのクラス型のインスタンスへの参照、またはそのクラス型から派生したクラスのインスタンスへの参照A null reference, a reference to an instance of that class type, or a reference to an instance of a class derived from that class type
  • インターフェイスの型Interface type
    • null 参照、そのインターフェイスの型を実装するクラス型のインスタンスへの参照、またはそのインターフェイス型を実装する値型のボックス化された値への参照A null reference, a reference to an instance of a class type that implements that interface type, or a reference to a boxed value of a value type that implements that interface type
  • 配列型Array type
    • null 参照、その配列型のインスタンスへの参照、または互換性のある配列型のインスタンスへの参照A null reference, a reference to an instance of that array type, or a reference to an instance of a compatible array type
  • デリゲート型Delegate type
    • null 参照、またはそのデリゲート型と互換性のあるインスタンスへの参照A null reference or a reference to an instance of a compatible delegate type

プログラムの構造Program structure

C# における主要な組織的概念は、"プログラム"、"名前空間"、""、"メンバー"、および "アセンブリ" です。The key organizational concepts in C# are programs, namespaces, types, members, and assemblies. プログラムは型を宣言します。型にはメンバーが含まれていて、複数の名前空間に編成することができます。Programs declare types, which contain members and can be organized into namespaces. 型の例には、クラス、構造体、インターフェイスがあります。Classes, structs, and interfaces are examples of types. メンバーの例には、フィールド、メソッド、プロパティ、およびイベントがあります。Fields, methods, properties, and events are examples of members. C# プログラムはコンパイルされると、物理的にアセンブリにパッケージ化されます。When C# programs are compiled, they're physically packaged into assemblies. アセンブリには通常、アプリケーションまたはライブラリのどちらかを実行するかに応じて、それぞれ .exe または .dll のファイル拡張子があります。Assemblies typically have the file extension .exe or .dll, depending on whether they implement applications or libraries, respectively.

小さな例として、次のコードを含むアセンブリについて考えてみます。As a small example, consider an assembly that contains the following code:

using System;

namespace Acme.Collections
{
    public class Stack<T>
    {
        Entry _top;
        
        public void Push(T data)
        {
            _top = new Entry(_top, data);
        }

        public T Pop()
        {
            if (_top == null)
            {
                throw new InvalidOperationException();
            }
            T result = _top.Data;
            _top = _top.Next;
            
            return result;
        }

        class Entry
        {
            public Entry Next { get; set; }
            public T Data { get; set; }
            
            public Entry(Entry next, T data)
            {
                Next = next;
                Data = data;
            }
        }
    }
}

このクラスの完全修飾名は Acme.Collections.Stack です。The fully qualified name of this class is Acme.Collections.Stack. このクラスには複数のメンバーが含まれています: top という名前のフィールドが 1 つ、PushPop という名前のメソッドが合わせて 2 つ、そして Entry という名前の入れ子になったクラスです。The class contains several members: a field named top, two methods named Push and Pop, and a nested class named Entry. Entry クラスにはさらに、3 つのメンバーが含まれています: next という名前のフィールド、data という名前のフィールド、およびコンストラクターです。The Entry class further contains three members: a field named next, a field named data, and a constructor. Stack は "ジェネリック" クラスです。The Stack is a generic class. これには、使用時に具象型に置き換えられる 1 つの型パラメーター T があります。It has one type parameter, T that is replaced with a concrete type when it's used.

注意

"スタック" は "先入れ後出し" (FILO) コレクションです。A stack is a "first in - last out" (FILO) collection. 新しい要素がスタックの先頭に追加されます。New elements are added to the top of the stack. 要素が削除されると、それはスタックの一番上から削除されます。When an element is removed, it is removed from the top of the stack.

アセンブリには実行可能なコードが中間言語 (IL) の形式で含まれていて、シンボル情報がメタデータの形式で含まれています。Assemblies contain executable code in the form of Intermediate Language (IL) instructions, and symbolic information in the form of metadata. 実行前に、.NET 共通言語ランタイムの Just-In-Time (JIT) コンパイラによって、アセンブリの IL コードはプロセッサ固有のコードに変換されます。Before it's executed, the Just-In-Time (JIT) compiler of .NET Common Language Runtime converts the IL code in an assembly to processor-specific code.

アセンブリはコードとメタデータの両方を含む自己記述的な機能的単位であるため、#include ディレクティブおよびヘッダー ファイルを C# に含める必要はありません。Because an assembly is a self-describing unit of functionality containing both code and metadata, there's no need for #include directives and header files in C#. 特定のアセンブリに含まれているパブリックの型とメンバーは、単にプログラムのコンパイル中にそのアセンブリを参照することにより、C# プログラムで利用可能になります。The public types and members contained in a particular assembly are made available in a C# program simply by referencing that assembly when compiling the program. たとえば、このプログラムでは acme.dll アセンブリの Acme.Collections.Stack クラスを使用しています。For example, this program uses the Acme.Collections.Stack class from the acme.dll assembly:

using System;
using Acme.Collections;

class Example
{
    public static void Main()
    {
        var s = new Stack<int>();
        s.Push(1); // stack contains 1
        s.Push(10); // stack contains 1, 10
        s.Push(100); // stack contains 1, 10, 100
        Console.WriteLine(s.Pop()); // stack contains 1, 10
        Console.WriteLine(s.Pop()); // stack contains 1
        Console.WriteLine(s.Pop()); // stack is empty
    }
}

このプログラムをコンパイルするには、前の例で定義されているスタック クラスを含むアセンブリを "参照" する必要があります。To compile this program, you would need to reference the assembly containing the stack class defined in the earlier example.

C# プログラムは複数のソース ファイルに格納できます。C# programs can be stored in several source files. C# プログラムがコンパイルされると、すべてのソース ファイルがまとめて処理され、ソース ファイルは自由に相互参照できます。When a C# program is compiled, all of the source files are processed together, and the source files can freely reference each other. 概念的には、処理される前にすべてのソース ファイルが 1 つの大きなファイルに連結されるかのようになります。Conceptually, it's as if all the source files were concatenated into one large file before being processed. C# では事前宣言をする必要がありません。ごく一部の例外を除いて、宣言の順序は重要でないためです。Forward declarations are never needed in C# because, with few exceptions, declaration order is insignificant. C# ではソース ファイルがパブリック型 1 つのみの宣言に制限されません。また、ソース ファイルの名前がソース ファイルで宣言された型に一致する必要もありません。C# doesn't limit a source file to declaring only one public type nor does it require the name of the source file to match a type declared in the source file.

これらの組織ブロックについては、このツアーの他の記事をご覧ください。Further articles in this tour explain these organizational blocks.