Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Du använder olika operatorer och uttryck för att komma åt en typmedlem. Medlemsåtkomstoperatorer inkluderar medlemsåtkomst (.
), matriselement eller indexeraråtkomst ([]
), index från slutpunkt (^
), intervall (..
), null-villkorsstyrda operatorer (?.
och ?[]
) och metodanrop (()
). Dessa operatorer inkluderar null-villkors-åtkomst till medlem (?.
) och åtkomst till indexerare (?[]
).
.
(medlemsåtkomst): för att få åtkomst till en medlem i ett namnområde eller en typ[]
(åtkomst till matriselement eller indexerare): för att komma åt ett matriselement eller en typindexerare?.
och?[]
(null-villkorsstyrda operatorer): att utföra en medlems- eller elementåtkomståtgärd endast om en operand inte är null()
(anrop): anropa en åtkomstmetod eller anropa ett ombud^
(index från slutet): för att indikera att elementpositionen kommer från slutet av en sekvens..
(intervall): för att ange ett intervall med index som du kan använda för att hämta ett intervall med sekvenselement
Medlemsåtkomstuttryck .
Du använder .
-token för att komma åt en medlem i ett namnområde eller en typ, som följande exempel visar:
- Använd
.
för att komma åt ett kapslat namnområde inom ett namnområde, som följande exempel på enusing
direktiv visar:
using System.Collections.Generic;
- Använd
.
för att skapa ett kvalificerat namn för att komma åt en typ i en namnrymd, som följande kod visar:
System.Collections.Generic.IEnumerable<int> numbers = [1, 2, 3];
Använd ett using
-direktiv för att göra användningen av kvalificerade namn valfri.
- Använd
.
för att komma åt typmedlemmar, statiska och icke-statiska, som följande kod visar:
List<double> constants =
[
Math.PI,
Math.E
];
Console.WriteLine($"{constants.Count} values to show:");
Console.WriteLine(string.Join(", ", constants));
// Output:
// 2 values to show:
// 3.14159265358979, 2.71828182845905
Du kan också använda .
för att komma åt en tilläggsmetod.
Operatorn för indexering []
Hakparenteser, []
, används vanligtvis för åtkomst till matriser, indexerare eller pekarelement. Från och med C# 12 omsluter []
ett samlingsuttryck.
Matrisåtkomst
I följande exempel visas hur du kommer åt matriselement:
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
Om ett index i en array ligger utanför gränserna för motsvarande dimension i arrayen genereras en IndexOutOfRangeException.
Som föregående exempel visar använder du även hakparenteser när du deklarerar en matristyp eller instansierar en matrisinstans.
För mer information om matriser, se Matriser.
Indexerarens åtkomst
I följande exempel används .NET-typen för att demonstrera indexeråtkomst:
var dict = new Dictionary<string, double>();
dict["one"] = 1;
dict["pi"] = Math.PI;
Console.WriteLine(dict["one"] + dict["pi"]); // output: 4.14159265358979
Med indexerare kan du indexera instanser av en användardefinierad typ på liknande sätt som matrisindexering. Till skillnad från matrisindex, som måste vara heltal, kan indexerarparametrarna deklareras vara av vilken typ som helst.
För mer information om indexerare, se Indexerare.
Andra användningar av []
Information om åtkomst till pekarelement finns i avsnittet Operator för åtkomst av pekarelement [] i artikeln Pekarerelaterade operatorer. För information om samlingsuttryck, se artikeln collection expressions.
Du använder också hakparenteser för att ange attribut:
[System.Diagnostics.Conditional("DEBUG")]
void TraceMethod() {}
Dessutom kan hakparenteser användas för att ange listmönster för användning i mönstermatchning eller testning.
arr is ([1, 2, ..])
//Specifies that an array starts with (1, 2)
Null-villkorsstyrda operatorer ?.
och ?[]
En null-villkorsoperator tillämpar endast en medlemsåtkomstoperation (?.
) eller elementåtkomst (?[]
) på dess operanden endast om operanden utvärderas som icke-null; annars returneras null
. Med andra ord:
Om
a
utvärderas tillnull
, är resultatet ava?.x
ellera?[x]
null
.Om
a
utvärderas till icke-null är resultatet ava?.x
ellera?[x]
detsamma som resultatet ava.x
ellera[x]
, respektive.Kommentar
Om
a.x
ellera[x]
utlöser ett undantag, kommera?.x
ellera?[x]
att utlösa samma undantag för icke-nulla
. Om till exempela
är en icke-null-arrayinstans ochx
ligger utanför gränserna föra
, skullea?[x]
utlösa en IndexOutOfRangeException.
De null-villkorsstyrda operatorerna kortsluter. Det vill säga, om en operation i en kedja av villkorsstyrda medlems- eller elementåtkomstoperationer returnerar null
, utförs inte resten av kedjan. I följande exempel utvärderas inte B
om A
utvärderas till null
och C
utvärderas inte om A
eller B
utvärderas till null
.
A?.B?.Do(C);
A?.B?[C];
Om A
kan vara null men B
och C
skulle inte vara null om A inte är null, behöver du bara tillämpa null-villkorsoperatorn på A
:
A?.B.C();
I föregående exempel utvärderas B
inte och C()
anropas inte om A
är null. Men om den länkade medlemsåtkomsten avbryts, till exempel av parenteser som i (A?.B).C()
, sker inte kortslutning.
Följande exempel demonstrerar användningen av ?.
- och ?[]
-operatorerna:
double SumNumbers(List<double[]> setsOfNumbers, int indexOfSetToSum)
{
return setsOfNumbers?[indexOfSetToSum]?.Sum() ?? double.NaN;
}
var sum1 = SumNumbers(null, 0);
Console.WriteLine(sum1); // output: NaN
List<double[]?> numberSets =
[
[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
namespace MemberAccessOperators2;
public static class NullConditionalShortCircuiting
{
public static void Main()
{
Person? person = null;
person?.Name.Write(); // no output: Write() is not called due to short-circuit.
try
{
(person?.Name).Write();
}
catch (NullReferenceException)
{
Console.WriteLine("NullReferenceException");
}; // output: NullReferenceException
}
}
public class Person
{
public required FullName Name { get; set; }
}
public class FullName
{
public required string FirstName { get; set; }
public required string LastName { get; set; }
public void Write() => Console.WriteLine($"{FirstName} {LastName}");
}
Det första exemplet ovan använder också operatorn ??
null-coalescing för att ange ett alternativt uttryck för att utvärdera om resultatet av en null-villkorsstyrd åtgärd är null
.
Om a.x
eller a[x]
är av en värdetyp som T
inte kan nullvärde , a?.x
eller a?[x]
är av motsvarande null-värdetypT?
. Om du behöver ett uttryck av typ T
, använd null-sammanslagningsoperatorn ??
på ett null-villkorsuttryck, som följande exempel visar.
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([])); // output: 0
Console.WriteLine(GetSumOfFirstTwoOrDefault([3, 4, 5])); // output: 7
I föregående exempel, om du inte använder ??
-operatorn, utvärderas numbers?.Length < 2
till false
när numbers
är null
.
Kommentar
Operatorn ?.
utvärderar sin vänstra operande högst en gång, vilket garanterar att den inte kan ändras till null
efter att ha verifierats som icke-null.
Från och med C# 14 är tilldelning tillåten med ett null-villkorsstyrd åtkomstuttryck (?.
och ?[]
) för referenstyper. Se till exempel följande metod:
person?.FirstName = "Scott";
messages?[5] = "five";
Föregående exempel visar tilldelning till en egenskap och ett indexerat element på en referenstyp som kan vara null. Ett viktigt beteende för den här tilldelningen är att uttrycket till höger =
endast utvärderas när den vänstra sidan är känd för att vara icke-null. I följande kod anropas funktionen GenerateNextIndex
till exempel endast när matrisen values
inte är null. Om matrisen values
är null GenerateNextIndex
anropas inte:
person?.FirstName = "Scott";
messages?[5] = "five";
Med andra ord motsvarar föregående kod följande kod med hjälp av en if
instruktion för null-kontrollen:
if (values is not null)
{
values[2] = GenerateNextIndex();
}
Förutom tilldelning tillåts alla former av sammansatt tilldelning, till exempel +=
eller -=
. Inkrement (++
) och decrement (--
) tillåts dock inte.
Den här förbättringen klassificerar inte ett villkorsuttryck för null som en variabel. Den kan inte ref
tilldelas, inte heller kan den tilldelas till en ref
variabel eller skickas till en metod som ett ref
eller out
argument.
Trådsäkert ombudsanrop
Använd operatorn ?.
för att kontrollera om en delegering inte är null och anropa den på ett trådsäkert sätt (till exempel när du genererar en händelse), som följande kod visar:
PropertyChanged?.Invoke(…)
Koden motsvarar följande kod:
var handler = this.PropertyChanged;
if (handler != null)
{
handler(…);
}
Föregående exempel är ett trådsäkert sätt att se till att endast en icke-null anropas. Eftersom delegerade instanser är oföränderliga kan ingen tråd ändra objektet som refereras av den handler
lokala variabeln. I synnerhet om koden som körs av en annan tråd avbryter prenumerationen från PropertyChanged
händelsen och PropertyChanged
blir null
innan handler
anropas, förblir objektet som refereras av handler
opåverkat.
Anropsuttryck ()
Använd parenteser, ()
, för att anropa en metod eller anropa en delegering.
Följande kod visar hur du anropar en metod, med eller utan argument, och anropar ett ombud:
Action<int> display = s => Console.WriteLine(s);
List<int> numbers =
[
10,
17
];
display(numbers.Count); // output: 2
numbers.Clear();
display(numbers.Count); // output: 0
Du använder också parenteser när du anropar en konstruktor med operatorn .
Andra användningar av ()
Du använder också parenteser för att justera ordningen för att utvärdera åtgärder i ett uttryck. Mer information finns i C#-operatorer.
Cast-uttryck, som utför explicita typomvandlingar, använder också parenteser.
Index från slutoperatorn ^
Index- och intervalloperatorer kan användas med en typ som kan räknas. En räknebar typ är en typ som har en egenskap med namnet antingen Count
eller Length
med en tillgänglig get
accessor. Samlingsuttryck förlitar sig också på antalstyper .
Kommentar
Endimensionella matriser kan räknas. Flerdimensionella matriser är inte det. Operatorerna ^
och ..
(intervallet) kan inte användas i flerdimensionella matriser.
Operatorn ^
anger elementets position från slutet av en sekvens. För en sekvens med längd length
, pekar ^n
på elementet med förskjutning length - n
från början av en sekvens. Exempelvis pekar ^1
på det sista elementet i en sekvens och ^length
på det första elementet i en sekvens.
int[] xs = [0, 10, 20, 30, 40];
int last = xs[^1];
Console.WriteLine(last); // output: 40
List<string> lines = ["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
Som föregående exempel visar är uttrycket ^e
av typen System.Index. I uttryck , måste resultatet av vara implicit konvertibelt till .
Du kan också använda operatorn ^
med intervalloperatorn för att skapa ett indexintervall. Mer information finns i Index och intervall.
Från och med C# 13 kan indexet från slutoperatorn användas i en objektinitierare.
Intervalloperator ..
Operatorn ..
anger början och slutet av ett indexintervall som operander. Den vänstra operanden är en inkluderande start på ett intervall. Den högra operand är en exklusiv ände av ett intervall. Någon av operanderna kan vara ett index från början eller från slutet av en sekvens, som följande exempel visar:
int[] numbers = [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));
Som föregående exempel visar är uttrycket a..b
av typen System.Range. I uttryck a..b
måste resultaten av a
och b
kunna implicit konverteras till Int32 eller Index.
Viktigt!
Implicita konverteringar från int
till Index
utlöser ett ArgumentOutOfRangeException när värdet är negativt.
Du kan utelämna något av operatorns operander ..
för att få ett intervall utan fast slutpunkt:
-
a..
är motsvarandea..^0
-
..b
är motsvarande0..b
-
..
är motsvarande0..^0
int[] numbers = [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));
I följande tabell visas olika sätt att uttrycka samlingsintervall:
Intervalloperatoruttryck | beskrivning |
---|---|
.. |
Alla värden i samlingen. |
..end |
Värden från början till slutet, uteslutande . |
start.. |
Värden från och med |
start..end |
Värden från start inklusive till end exklusivt. |
^start.. |
Värden från start och framåt till slut, räknat från slutet. |
..^end |
Värden från början till end exklusive och räknande bakåt från slutet. |
start..^end |
Värden från start inkluderande till end uteslutande med början från slutet. |
^start..^end |
Värden från start inkluderande till end uteslutande båda räknar från slutet. |
I följande exempel visas effekten av att använda alla intervall som visas i föregående tabell:
int[] oneThroughTen =
[
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
];
Write(oneThroughTen, ..);
Write(oneThroughTen, ..3);
Write(oneThroughTen, 2..);
Write(oneThroughTen, 3..5);
Write(oneThroughTen, ^2..);
Write(oneThroughTen, ..^3);
Write(oneThroughTen, 3..^4);
Write(oneThroughTen, ^4..^2);
static void Write(int[] values, Range range) =>
Console.WriteLine($"{range}:\t{string.Join(", ", values[range])}");
// Sample output:
// 0..^0: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
// 0..3: 1, 2, 3
// 2..^0: 3, 4, 5, 6, 7, 8, 9, 10
// 3..5: 4, 5
// ^2..^0: 9, 10
// 0..^3: 1, 2, 3, 4, 5, 6, 7
// 3..^4: 4, 5, 6
// ^4..^2: 7, 8
Mer information finns i Index och intervall.
..
-token används också för spridningselementet i ett samlingsuttryck.
Möjlighet till operatoröverbelastning
Operatörerna
, .
,
, och
kan inte överbelastas. Operatorn
[]
anses också vara en icke-överbelastningsbar operator. Använd indexatorer för att stödja indexering med användardefinierade typer.
Språkspecifikation för C#
Mer information finns i följande avsnitt i C#-språkspecifikationen:
- Medlemsåtkomst
- Elementåtkomst
- Nullvillkorlig åtkomst av medlemmar
- Anropsuttryck
Mer information om index och intervall finns i funktionsförslagsanteckningen.
Se även
- Använda indexoperator (formatregel IDE0056)
- Använd intervalloperatorn (formatregel IDE0057)
- Använda villkorsstyrd delegeringsanrop (regel IDE1005)
- C#-operatorer och uttryck
- ?? (null-sammanslagningsoperator)
- ::operatör