Operadores y expresiones de acceso a miembros (referencia de C#)Member access operators and expressions (C# reference)

Puede usar los operadores y expresiones siguientes cuando accede a un miembro de tipo:You can use the following operators and expressions when you access a type member:

Expresión de acceso a miembros.Member access expression .

Use el token . para acceder a un miembro de un espacio de nombres o un tipo, como se muestran en los ejemplos siguientes:You use the . token to access a member of a namespace or a type, as the following examples demonstrate:

  • Use . para acceder a un espacio de nombres anidado dentro de un espacio de nombres, como se muestra en el siguiente ejemplo de una directiva using:Use . to access a nested namespace within a namespace, as the following example of a using directive shows:

    using System.Collections.Generic;
    
  • Use . para formar un nombre completo para tener acceso a un tipo dentro de un espacio de nombres, como se muestra en el código siguiente: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 };
    

    Utilice una directiva using para hacer que el uso de nombres completos sea opcional.Use a using directive to make the use of qualified names optional.

  • Use . para tener acceso a los miembros de tipo, que no son estáticos y, como se muestra en el código siguiente: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
    

También puede usar . para acceder a un método de extensión.You can also use . to access an extension method.

Operador del indizador []Indexer operator []

Los corchetes, [], se suelen usar para el acceso a matriz, indizador o elemento de puntero.Square brackets, [], are typically used for array, indexer, or pointer element access.

Acceso a matrizArray access

En el ejemplo siguiente se muestra cómo se obtiene acceso a los elementos de matriz: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

Si un índice de matriz se encuentra fuera de los límites de la dimensión correspondiente de una matriz, se produce una excepción IndexOutOfRangeException.If an array index is outside the bounds of the corresponding dimension of an array, an IndexOutOfRangeException is thrown.

Tal como se muestra en el ejemplo anterior, también usa corchetes al declarar un tipo de matriz o crear instancias de matriz.As the preceding example shows, you also use square brackets when you declare an array type or instantiate an array instance.

Para obtener más información sobre las matrices, consulte Matrices.For more information about arrays, see Arrays.

Acceso a indizadorIndexer access

En el ejemplo siguiente se usa el tipo Dictionary<TKey,TValue> de .NET para mostrar el acceso al indizador: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

Los indizadores le permiten indizar las instancias de un tipo definido por el usuario de un modo similar a la indización de matrices.Indexers allow you to index instances of a user-defined type in the similar way as array indexing. A diferencia de los índices de matriz, que deben ser enteros, los parámetros de indizador se pueden declarar para ser de cualquier tipo.Unlike array indices, which must be integer, the indexer parameters can be declared to be of any type.

Para más información sobre los indizadores, consulte Indizadores.For more information about indexers, see Indexers.

Otros usos de []Other usages of []

Para información sobre el acceso de los elementos de puntero, consulte la sección Operador de acceso de elemento de puntero del artículo Operadores relacionados con el puntero.For information about pointer element access, see the Pointer element access operator [] section of the Pointer related operators article.

También usa los corchetes para especificar atributos:You also use square brackets to specify attributes:

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

Operadores condicionales NULL ?.Null-conditional operators ?. y ?[]and ?[]

Disponible en C# 6 y versiones posteriores, un operador condicional NULL aplica una operación de acceso a miembros, ?., o acceso a elementos, ?[], a su operando solo si dicho operando se evalúa como no 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. Es decir:That is,

  • Si a se evalúa como null, el resultado de a?.x o a?[x] es null.If a evaluates to null, the result of a?.x or a?[x] is null.

  • Si a se evalúa como no NULL, el resultado de a?.x o a?[x] es el mismo que el resultado de a.x o a[x], respectivamente.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.

    Nota

    Si a.x o a[x] producen una excepción, a?.x o a?[x] produciría la misma excepción para a no NULL.If a.x or a[x] throws an exception, a?.x or a?[x] would throw the same exception for non-null a. Por ejemplo, si a es una instancia de matriz que no es NULL y x está fuera de los límites de a, a?[x] produciría una excepción 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.

Los operadores de condición NULL se cortocircuitan.The null-conditional operators are short-circuiting. Es decir, si una operación en una cadena de la operación de acceso a elementos o miembros condicional devuelve null, no se ejecuta el resto de la cadena.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. En el ejemplo siguiente, B no se evalúa si A se evalúa como null y C no se evalúa si A o B se evalúan como null: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];

En el siguiente ejemplo se muestra el uso de los operadores ?. y ?[]: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

En el ejemplo anterior también se usa el operador de fusión de NULL ?? para especificar una expresión alternativa que se evaluará en caso de que el resultado de la operación condicional NULL sea 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.

Si a.x o a[x] es de un tipo de valor que no admite un valor NULL, T, a?.x o a?[x] es del tipo de valor que admite un valor NULL T? correspondiente.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?. Si necesita una expresión de tipo T, aplique el operador de fusión de NULL ?? a una expresión condicional NULL, tal como se muestra en el ejemplo siguiente: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

En el ejemplo anterior, si no utiliza el operador ??, numbers?.Length < 2 da como resultado false cuando numbers es null.In the preceding example, if you don't use the ?? operator, numbers?.Length < 2 evaluates to false when numbers is null.

El operador de acceso de miembro condicional NULL ?. también se conoce con el nombre de operador Elvis.The null-conditional member access operator ?. is also known as the Elvis operator.

Invocación de delegado seguro para subprocesosThread-safe delegate invocation

Use el operador ?. para comprobar si un delegado es distinto de NULL y se invoca de forma segura para subprocesos (por ejemplo, cuando se genera un evento), tal como se muestra en el código siguiente: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(…)

Ese código es equivalente al código siguiente que se usaría en C# 5 o una versión anterior: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(…);
}

Es un modo seguro para subprocesos de asegurarse de que solo se invoca un handler que no es NULL.That is a thread-safe way to ensure that only a non-null handler is invoked. Dado que las instancias de delegado son inmutables, ningún subproceso puede cambiar el valor al que hace referencia la variable local handler.Because delegate instances are immutable, no thread can change the object referenced by the handler local variable. En concreto, si el código que ha ejecutado otro subproceso cancela la suscripción del evento PropertyChanged y PropertyChanged se convierte en null antes de que se invoque handler, el objeto al que hace referencia handler queda intacto.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. El operador ?. evalúa el operando de la izquierda no más de una vez, lo que garantiza que no se pueda cambiar a null después de verificarse como no 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.

Expresión de invocación ()Invocation expression ()

Utilice paréntesis, (), para llamar a un método o invocar un delegado.Use parentheses, (), to call a method or invoke a delegate.

En el ejemplo siguiente se muestra cómo llamar a un método, con o sin argumentos, y cómo invocar un delegado: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

También usa paréntesis al invocar un constructor con el operador new.You also use parentheses when you invoke a constructor with the new operator.

Otros usos de ()Other usages of ()

También usa los paréntesis para ajustar el orden en el que se van a evaluar operaciones en una expresión.You also use parentheses to adjust the order in which to evaluate operations in an expression. Para obtener más información, vea Operadores de C# (referencia de C#).For more information, see C# operators.

Expresiones de conversión, que realizan conversiones de tipo explícitas, también utilizan paréntesis.Cast expressions, which perform explicit type conversions, also use parentheses.

Indexación desde el operador final ^Index from end operator ^

Disponible en C# 8.0 y versiones posteriores, el operador ^ indica la posición del elemento a partir del final de una secuencia.Available in C# 8.0 and later, the ^ operator indicates the element position from the end of a sequence. En el caso de una secuencia de longitud length, ^n apunta al elemento con desplazamiento length - n desde el inicio de una secuencia.For a sequence of length length, ^n points to the element with offset length - n from the start of a sequence. Por ejemplo, ^1 apunta al último elemento de una secuencia y ^length apunta al primer elemento de una secuencia.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

Como se muestra en el ejemplo anterior, la expresión ^e es del tipo System.Index.As the preceding example shows, expression ^e is of the System.Index type. En la expresión ^e, el resultado de e debe poderse convertir implícitamente a int.In expression ^e, the result of e must be implicitly convertible to int.

También puede usar el operador ^ con el operador de intervalo para crear un intervalo de índices.You can also use the ^ operator with the range operator to create a range of indices. Para más información, consulte Índices y rangos.For more information, see Indices and ranges.

Operador de intervalo .Range operator ..

Disponible en C# 8.0 y versiones posteriores, el operador .. especifica el inicio y el final de un intervalo de índices como sus operandos.Available in C# 8.0 and later, the .. operator specifies the start and end of a range of indices as its operands. El operando izquierdo es un inicio inclusivo de un intervalo.The left-hand operand is an inclusive start of a range. El operando derecho es un inicio exclusivo de un intervalo.The right-hand operand is an exclusive end of a range. Cualquiera de los operandos puede ser un índice desde el inicio o desde el final de una secuencia, tal y como muestra el ejemplo siguiente: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));

Como se muestra en el ejemplo anterior, la expresión a..b es del tipo System.Range.As the preceding example shows, expression a..b is of the System.Range type. En la expresión a..b, los resultados de a y b deben poderse convertir implícitamente a int o Index.In expression a..b, the results of a and b must be implicitly convertible to int or Index.

Puede omitir cualquiera de los operandos del operador .. para obtener un intervalo abierto:You can omit any of the operands of the .. operator to obtain an open-ended range:

  • a.. es equivalente a a..^0a.. is equivalent to a..^0
  • ..b es equivalente a 0..b..b is equivalent to 0..b
  • .. es equivalente a 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));

Para más información, consulte Índices y rangos.For more information, see Indices and ranges.

Posibilidad de sobrecarga del operadorOperator overloadability

Los operadores ., (), ^ y .. no se pueden sobrecargar.The ., (), ^, and .. operators cannot be overloaded. El operador [] también se considera un operador que no se puede sobrecargar.The [] operator is also considered a non-overloadable operator. Use indizadores para admitir la indización con tipos definidos por el usuario.Use indexers to support indexing with user-defined types.

Especificación del lenguaje C#C# language specification

Para más información, vea las secciones siguientes de la Especificación del lenguaje C#:For more information, see the following sections of the C# language specification:

Para más información sobre índices y rangos, vea la nota de propuesta de características.For more information about indices and ranges, see the feature proposal note.

Vea tambiénSee also