メンバー アクセス演算子と式 (C# リファレンス)Member access operators and expressions (C# reference)

型のメンバーにアクセスするときは、次の演算子と式を使用できます。You can use the following operators and expressions when you access a type member:

メンバー アクセス式 .Member access expression .

以下の例に示すように、名前空間のメンバーまたは型にアクセスするために . トークンを使います。You use the . token to access a member of a namespace or a type, as the following examples demonstrate:

  • 次の using ディレクティブの例に示すように、. を使って、名前空間内の入れ子になった名前空間にアクセスします。Use . to access a nested namespace within a namespace, as the following example of a using directive shows:

    using System.Collections.Generic;
    
  • 次のコードに示すように、. を使って "修飾名" を作成して名前空間内の型にアクセスします。Use . to form a qualified name to access a type within a namespace, as the following code shows:

    System.Collections.Generic.IEnumerable<int> numbers = new int[] { 1, 2, 3 };
    

    using ディレクティブを使い、必要に応じて修飾名を利用します。Use a using directive to make the use of qualified names optional.

  • 次のコードに示すように、. を使って、型のメンバー (静的および非静的) にアクセスします。Use . to access type members, static and non-static, as the following code shows:

    var constants = new List<double>();
    constants.Add(Math.PI);
    constants.Add(Math.E);
    Console.WriteLine($"{constants.Count} values to show:");
    Console.WriteLine(string.Join(", ", constants));
    // Output:
    // 2 values to show:
    // 3.14159265358979, 2.71828182845905
    

また、. を使って拡張メソッドにアクセスすることもできます。You can also use . to access an extension method.

インデクサー演算子 []Indexer operator []

通常、角かっこ [] は、配列、インデクサー、またはポインター要素へのアクセスに使用されます。Square brackets, [], are typically used for array, indexer, or pointer element access.

配列へのアクセスArray access

次の例は、配列要素へのアクセス方法を示しています。The following example demonstrates how to access array elements:

int[] fib = new int[10];
fib[0] = fib[1] = 1;
for (int i = 2; i < fib.Length; i++)
{
    fib[i] = fib[i - 1] + fib[i - 2];
}
Console.WriteLine(fib[fib.Length - 1]);  // output: 55

double[,] matrix = new double[2,2];
matrix[0,0] = 1.0;
matrix[0,1] = 2.0;
matrix[1,0] = matrix[1,1] = 3.0;
var determinant = matrix[0,0] * matrix[1,1] - matrix[1,0] * matrix[0,1];
Console.WriteLine(determinant);  // output: -3

配列インデックスが配列の対応するディメンションの範囲に含まれない場合、IndexOutOfRangeException がスローされます。If an array index is outside the bounds of the corresponding dimension of an array, an IndexOutOfRangeException is thrown.

前述の例が示すように、配列型の宣言と配列インスタンスのインスタンス化にも角かっこを使用します。As the preceding example shows, you also use square brackets when you declare an array type or instantiate an array instance.

配列の詳細については、「配列」を参照してください。For more information about arrays, see Arrays.

インデクサーへのアクセスIndexer access

次の例では、インデクサーへのアクセスを示すために .NET Dictionary<TKey,TValue> 型を使用します。The following example uses the .NET Dictionary<TKey,TValue> type to demonstrate indexer access:

var dict = new Dictionary<string, double>();
dict["one"] = 1;
dict["pi"] = Math.PI;
Console.WriteLine(dict["one"] + dict["pi"]);  // output: 4.14159265358979

インデクサーを使用すると、配列のインデックス作成と同様の方法でユーザー定義型のインスタンスのインデックスを作成することができます。Indexers allow you to index instances of a user-defined type in the similar way as array indexing. 整数である必要がある配列インデックスとは異なり、任意の型を持つインデクサー パラメーターを宣言できます。Unlike array indices, which must be integer, the indexer parameters can be declared to be of any type.

インデクサーの詳細については、「インデクサー」を参照してください。For more information about indexers, see Indexers.

[] の他の使用方法Other usages of []

ポインター要素へのアクセスの詳細については、ポインターに関連する演算子に関する記事の「ポインター要素アクセス演算子 []」セクションを参照してください。For information about pointer element access, see the Pointer element access operator [] section of the Pointer related operators article.

角かっこは、属性を指定するためにも使用されます。You also use square brackets to specify attributes:

[System.Diagnostics.Conditional("DEBUG")]
void TraceMethod() {}

Null 条件演算子 ?.Null-conditional operators ?. および ?[]and ?[]

C# 6 以降で使用できる Null 条件付き演算子は、そのオペランドが null 以外と評価された場合にのみ、オペランドにメンバー アクセス操作 (?.) または要素アクセス操作 (?[]) を適用し、それ以外の場合は、null を返します。Available in C# 6 and later, a null-conditional operator applies a member access, ?., or element access, ?[], operation to its operand only if that operand evaluates to non-null; otherwise, it returns null. つまり、以下のようになります。That is,

  • anull と評価された場合、a?.x または a?[x] の結果は null です。If a evaluates to null, the result of a?.x or a?[x] is null.

  • a が null 以外と評価された場合、a?.x または a?[x] の結果は、a.x または a[x] の結果とそれぞれ同じです。If a evaluates to non-null, the result of a?.x or a?[x] is the same as the result of a.x or a[x], respectively.

    注意

    a.x または a[x] が例外をスローした場合は、a?.x または a?[x] が、null 以外の a に対して同じ例外をスローします。If a.x or a[x] throws an exception, a?.x or a?[x] would throw the same exception for non-null a. たとえば、a が null 以外の配列インスタンスで、xaの範囲外にある場合、a?[x]IndexOutOfRangeException をスローします。For example, if a is a non-null array instance and x is outside the bounds of a, a?[x] would throw an IndexOutOfRangeException.

Null 条件演算子はショートサーキットです。The null-conditional operators are short-circuiting. つまり、条件付きのメンバーまたは要素アクセス操作のチェーン内にある 1 つの操作から null が返された場合、残りのチェーンは実行されません。That is, if one operation in a chain of conditional member or element access operations returns null, the rest of the chain doesn't execute. 次の例では、Anull と評価されると B は評価されず、A または Bnull と評価されると C は評価されません。In the following example, B is not evaluated if A evaluates to null and C is not evaluated if A or B evaluates to null:

A?.B?.Do(C);
A?.B?[C];

?. および ?[] 演算子の使用例を次に示します。The following example demonstrates the usage of the ?. and ?[] operators:

double SumNumbers(List<double[]> setsOfNumbers, int indexOfSetToSum)
{
    return setsOfNumbers?[indexOfSetToSum]?.Sum() ?? double.NaN;
}

var sum1 = SumNumbers(null, 0);
Console.WriteLine(sum1);  // output: NaN

var numberSets = new List<double[]>
{
    new[] { 1.0, 2.0, 3.0 },
    null
};

var sum2 = SumNumbers(numberSets, 0);
Console.WriteLine(sum2);  // output: 6

var sum3 = SumNumbers(numberSets, 1);
Console.WriteLine(sum3);  // output: NaN

前の例では、null 条件演算の結果が null の場合に評価する代替の式を指定するために、null 合体演算子 ?? も使用しています。The preceding example also uses the null-coalescing operator ?? to specify an alternative expression to evaluate in case the result of a null-conditional operation is null.

a.x または a[x] が null 非許容値型の T の場合は、a?.x または a?[x] は対応する null 許容値型T? になります。If a.x or a[x] is of a non-nullable value type T, a?.x or a?[x] is of the corresponding nullable value type T?. T 型の式が必要な場合は、次の例に示すように、null 合体演算子 ?? を null 条件式に適用します。If you need an expression of type T, apply the null-coalescing operator ?? to a null-conditional expression, as the following example shows:

int GetSumOfFirstTwoOrDefault(int[] numbers)
{
    if ((numbers?.Length ?? 0) < 2)
    {
        return 0;
    }
    return numbers[0] + numbers[1];
}

Console.WriteLine(GetSumOfFirstTwoOrDefault(null));  // output: 0
Console.WriteLine(GetSumOfFirstTwoOrDefault(new int[0]));  // output: 0
Console.WriteLine(GetSumOfFirstTwoOrDefault(new[] { 3, 4, 5 }));  // output: 7

前の例では、?? 演算子を使用しなければ、numbersnull の場合、numbers?.Length < 2false と評価されます。In the preceding example, if you don't use the ?? operator, numbers?.Length < 2 evaluates to false when numbers is null.

Null 条件メンバー アクセス演算子 ?. は Elvis 演算子とも呼ばれます。The null-conditional member access operator ?. is also known as the Elvis operator.

注意

C# 8 では、null を許容する演算子は、前の null 条件演算のリストを終了します。In C# 8, the null-forgiving operator terminates the list of preceding null-conditional operations. たとえば、式 x?.y!.z(x?.y)!.z として解析されます。For example, the expression x?.y!.z is parsed as (x?.y)!.z. この解釈のため、xnull の場合でも z が評価されるため、NullReferenceException が発生する可能性があります。Due to this interpretation, z is evaluated even if x is null, which may result in a NullReferenceException.

スレッドセーフなデリゲートの呼び出しThread-safe delegate invocation

次のコードに示すように、?. 演算子を使用してデリゲートが null 以外かどうかを確認し、それをスレッドセーフな方法で呼び出します (たとえば、イベントを発生させる場合)。Use the ?. operator to check if a delegate is non-null and invoke it in a thread-safe way (for example, when you raise an event), as the following code shows:

PropertyChanged?.Invoke(…)

このコードは、C# 5 以前で使用する次のコードと同等です。That code is equivalent to the following code that you would use in C# 5 or earlier:

var handler = this.PropertyChanged;
if (handler != null)
{
    handler(…);
}

これは、null 以外の handler のみが呼び出されるようにするためのスレッドセーフな方法です。That is a thread-safe way to ensure that only a non-null handler is invoked. デリゲート インスタンスは不変であるため、handler ローカル変数によって参照されるオブジェクトを変更できるスレッドはありません。Because delegate instances are immutable, no thread can change the object referenced by the handler local variable. 具体的には、別のスレッドによって実行されるコードが PropertyChanged イベントから登録解除され、handler が呼び出される前に PropertyChangednull になる場合、handler によって参照されるオブジェクトは影響を受けません。In particular, if the code executed by another thread unsubscribes from the PropertyChanged event and PropertyChanged becomes null before handler is invoked, the object referenced by handler remains unaffected. ?. 演算子では、左側のオペランドが 1 回だけ評価され、null 以外として検証された後に null に変更できないことが保証されます。The ?. operator evaluates its left-hand operand no more than once, guaranteeing that it cannot be changed to null after being verified as non-null.

呼び出し式 ()Invocation expression ()

かっこ () は、メソッドを呼び出すとき、またはデリゲートを呼び出すときに使用します。Use parentheses, (), to call a method or invoke a delegate.

メソッドを呼び出す方法 (引数を指定した場合と指定しない場合) とデリゲートを呼び出す方法の例を次に示します。The following example demonstrates how to call a method, with or without arguments, and invoke a delegate:

Action<int> display = s => Console.WriteLine(s);

var numbers = new List<int>();
numbers.Add(10);
numbers.Add(17);
display(numbers.Count);   // output: 2

numbers.Clear();
display(numbers.Count);   // output: 0

かっこは、new 演算子を使用してコンストラクターを呼び出すときにも使用します。You also use parentheses when you invoke a constructor with the new operator.

() の他の使用方法Other usages of ()

式に含まれる演算を評価する順序を調整する場合にもかっこを使用します。You also use parentheses to adjust the order in which to evaluate operations in an expression. 詳細については、C# 演算子に関するページを参照してください。For more information, see C# operators.

明示的な型変換を実行するキャスト式でも、かっこが使われます。Cast expressions, which perform explicit type conversions, also use parentheses.

末尾からのインデックス演算子 ^Index from end operator ^

^ 演算子は C# 8.0 以降で使用することができ、要素の位置がシーケンスの末尾からであることを示します。Available in C# 8.0 and later, the ^ operator indicates the element position from the end of a sequence. 長さが length のシーケンスの場合、^n は、シーケンスの先頭からのオフセットが length - n である要素を指します。For a sequence of length length, ^n points to the element with offset length - n from the start of a sequence. たとえば、^1 は、シーケンスの最後の要素を指し、^length は、シーケンスの最初の要素を指します。For example, ^1 points to the last element of a sequence and ^length points to the first element of a sequence.

int[] xs = new[] { 0, 10, 20, 30, 40 };
int last = xs[^1];
Console.WriteLine(last);  // output: 40

var lines = new List<string> { "one", "two", "three", "four" };
string prelast = lines[^2];
Console.WriteLine(prelast);  // output: three

string word = "Twenty";
Index toFirst = ^word.Length;
char first = word[toFirst];
Console.WriteLine(first);  // output: T

前の例で示すように、式 ^eSystem.Index 型です。As the preceding example shows, expression ^e is of the System.Index type. ^eで、e の結果は int に暗黙に変換される必要があります。In expression ^e, the result of e must be implicitly convertible to int.

さらに、^ 演算子を範囲演算子 と組み合わせて使用してインデックスの範囲を作成することもできます。You can also use the ^ operator with the range operator to create a range of indices. 詳細については、「インデックスと範囲」を参照してください。For more information, see Indices and ranges.

範囲演算子 .Range operator ..

.. 演算子は C# 8.0 以降で使用することができ、インデックスの範囲の先頭と末尾をオペランドとして指定します。Available in C# 8.0 and later, the .. operator specifies the start and end of a range of indices as its operands. 左側のオペランドは "包含的" で、範囲の先頭を含みます。The left-hand operand is an inclusive start of a range. 右側のオペランドは "排他的" で、範囲の末尾を含みません。The right-hand operand is an exclusive end of a range. 次の例で示すように、どちらのオペランドであっても、シーケンスの先頭または末尾からのインデックスとすることができます。Either of operands can be an index from the start or from the end of a sequence, as the following example shows:

int[] numbers = new[] { 0, 10, 20, 30, 40, 50 };
int start = 1;
int amountToTake = 3;
int[] subset = numbers[start..(start + amountToTake)];
Display(subset);  // output: 10 20 30

int margin = 1;
int[] inner = numbers[margin..^margin];
Display(inner);  // output: 10 20 30 40

string line = "one two three";
int amountToTakeFromEnd = 5;
Range endIndices = ^amountToTakeFromEnd..^0;
string end = line[endIndices];
Console.WriteLine(end);  // output: three

void Display<T>(IEnumerable<T> xs) => Console.WriteLine(string.Join(" ", xs));

前の例で示すように、式 a..bSystem.Range 型です。As the preceding example shows, expression a..b is of the System.Range type. a..b で、a および b の結果は暗黙に int または Index に変換される必要があります。In expression a..b, the results of a and b must be implicitly convertible to int or Index.

.. 演算子のオペランドのいずれかを省略して、変更可能な範囲を取得することができます。You can omit any of the operands of the .. operator to obtain an open-ended range:

  • a..a..^0 と同じです。a.. is equivalent to a..^0
  • ..b0..b と同じです。..b is equivalent to 0..b
  • ..0..^0 と同じです。.. is equivalent to 0..^0
int[] numbers = new[] { 0, 10, 20, 30, 40, 50 };
int amountToDrop = numbers.Length / 2;

int[] rightHalf = numbers[amountToDrop..];
Display(rightHalf);  // output: 30 40 50

int[] leftHalf = numbers[..^amountToDrop];
Display(leftHalf);  // output: 0 10 20

int[] all = numbers[..];
Display(all);  // output: 0 10 20 30 40 50

void Display<T>(IEnumerable<T> xs) => Console.WriteLine(string.Join(" ", xs));

詳細については、「インデックスと範囲」を参照してください。For more information, see Indices and ranges.

演算子のオーバーロード可/不可Operator overloadability

.()^、および .. の各演算子はオーバーロードできません。The ., (), ^, and .. operators cannot be overloaded. [] 演算子も、オーバーロードできない演算子と見なされます。The [] operator is also considered a non-overloadable operator. ユーザー定義型を使用したインデックス作成をサポートするには、インデクサーを使用してください。Use indexers to support indexing with user-defined types.

C# 言語仕様C# language specification

詳細については、「C# 言語仕様」の次のセクションを参照してください。For more information, see the following sections of the C# language specification:

インデックスと範囲について詳しくは、機能提案メモを参照してください。For more information about indices and ranges, see the feature proposal note.

関連項目See also