Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
U gebruikt verschillende operators en expressies om toegang te krijgen tot een typelid. Operators voor lidtoegang omvatten lidtoegangsoperatoren (.
), matrixelementen of indexertoegang ([]
), index-vanuit-het-einde (^
), bereik (..
), null-voorwaardelijke bewerkingen (?.
en ?[]
) en methode-aanroep (()
). Deze operators omvatten de operatoren voor null-voorwaardelijke lidtoegang (?.
) en indexeerfunctietoegang (?[]
).
-
.
(lidtoegang): toegang krijgen tot een lid van een naamruimte of een type -
[]
(toegang tot matrixelement of indexeerfunctie): voor toegang tot een matrixelement of een typeindexeerfunctie -
?.
en?[]
(null-voorwaardelijke operators): als u alleen een bewerking voor lid- of elementtoegang wilt uitvoeren als een operand niet null is -
()
(aanroep): een geopende methode aanroepen of een gemachtigde aanroepen -
^
(index vanaf het einde): om aan te geven dat de elementpositie vanuit het einde van een reeks komt -
..
(bereik): om een reeks indexen op te geven die u kunt gebruiken om een reeks reekselementen te verkrijgen
Lidtoegangsexpressie .
U gebruikt het .
token om toegang te krijgen tot een lid van een naamruimte of een type, zoals in de volgende voorbeelden wordt gedemonstreert:
- Gebruik
.
om toegang te krijgen tot een geneste naamruimte binnen een naamruimte, zoals het volgende voorbeeld van eenusing
directive laat zien:
using System.Collections.Generic;
- Gebruik
.
om een gekwalificeerde naam te vormen voor toegang tot een type binnen een naamruimte, zoals de volgende code laat zien:
System.Collections.Generic.IEnumerable<int> numbers = [1, 2, 3];
Gebruik een using
richtlijn om het gebruik van gekwalificeerde namen optioneel te maken.
- Gebruik
.
om toegang te krijgen tot typelid, statisch en niet-statisch, zoals in de volgende code wordt weergegeven.
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
U kunt ook .
gebruiken om een extensiemethode te benaderen.
Operator voor indexeerfunctie []
Vierkante haken, []
worden meestal gebruikt voor toegang tot matrices, indexeerfuncties of aanwijzerelementen. Vanaf C# 12 omvat []
een verzamelingsexpressie.
Toegang tot matrices
In het volgende voorbeeld ziet u hoe u toegang hebt tot matrixelementen:
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
Als een matrixindex buiten de grenzen van de corresponderende dimensie van een matrix valt, wordt er een IndexOutOfRangeException gegenereerd.
Zoals in het voorgaande voorbeeld wordt weergegeven, gebruikt u ook vierkante haken wanneer u een matrixtype declareert of een matrixexemplaren instantiëren.
Zie Matrices voor meer informatie over matrices.
Toegang tot indexeerfunctie
In het volgende voorbeeld wordt het .NET-type Dictionary<TKey,TValue> gebruikt om de toegang tot de indexeerfunctie te demonstreren:
var dict = new Dictionary<string, double>();
dict["one"] = 1;
dict["pi"] = Math.PI;
Console.WriteLine(dict["one"] + dict["pi"]); // output: 4.14159265358979
Met indexeerfuncties kunt u exemplaren van een door de gebruiker gedefinieerd type op dezelfde manier indexeren als matrixindexering. In tegenstelling tot matrixindexen, die geheel getal moeten zijn, kunnen de indexeerparameters van elk type worden gedeclareerd.
Zie Indexeerfuncties voor meer informatie over indexeerfuncties.
Andere gebruiksgegevens van []
Voor informatie over toegang tot pointer-elementen, zie de sectie Pointer-elementtoegangsoperator [] van het artikel aanwijzer-gerelateerde operators. Zie het artikel verzamelingsexpressies voor informatie over verzamelingsexpressies .
U gebruikt ook vierkante haken om kenmerken op te geven:
[System.Diagnostics.Conditional("DEBUG")]
void TraceMethod() {}
Daarnaast kunnen vierkante haken worden gebruikt om lijstpatronen aan te wijzen voor gebruik in patroonkoppeling of testen.
arr is ([1, 2, ..])
//Specifies that an array starts with (1, 2)
Null-voorwaardelijke operators ?.
en ?[]
Een null-conditionele operator past een lidtoegangbewerking (?.
) of elementtoegang (?[]
) alleen toe op de operand als de operand niet-null evalueert; anders wordt anders geretourneerd null
. Met andere woorden:
Als
a
wordt geëvalueerd alsnull
, dan is het resultaat vana?.x
ofa?[x]
null
.Als
a
dit resulteert in een niet-null-waarde, is het resultaat vana?.x
ofa?[x]
hetzelfde als respectievelijk het resultaat vana.x
ofa[x]
, respectievelijk.Opmerking
Als
a.x
ofa[x]
een uitzondering genereert, dan zoudena?.x
ofa?[x]
dezelfde uitzondering genereren voor niet-nula
. Alsa
bijvoorbeeld een niet-null array-instantie is enx
zich buiten de grenzen vana
bevindt, gooita?[x]
een IndexOutOfRangeException.
De null-voorwaardelijke operators voeren kortsluiting uit. Als één bewerking in een keten van voorwaardelijke lid- of elementtoegangsbewerkingen retourneert null
, wordt de rest van de keten niet uitgevoerd. In het volgende voorbeeld wordt B
niet geëvalueerd als A
als null
wordt geëvalueerd, en C
wordt niet geëvalueerd als A
of B
tot null
wordt geëvalueerd.
A?.B?.Do(C);
A?.B?[C];
Als A
null zou kunnen zijn, maar B
en C
niet null zouden zijn als A niet null is, hoeft u alleen de null-voorwaardelijke operator toe te passen op A
:
A?.B.C();
In het voorgaande voorbeeld B
wordt deze niet geëvalueerd en C()
wordt deze niet aangeroepen als A
null is. Als de toegang tot gekoppelde leden echter wordt onderbroken, bijvoorbeeld door haakjes zoals in (A?.B).C()
, gebeurt kortsluiting niet.
In de volgende voorbeelden ziet u het gebruik van de ?.
en ?[]
operators:
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}");
}
In het eerste vorige voorbeeld wordt ook de null-coalescing-operator ??
gebruikt om een alternatieve uitdrukking op te geven voor het geval dat het resultaat van een null-voorwaardelijke bewerking null
is.
Als a.x
of a[x]
van een niet-nullable waarde type T
is, is a?.x
of a?[x]
van het overeenkomstige nullable waardetype T?
. Als u een expressie van het type T
nodig hebt, past u de operator ??
null-coalescing toe op een null-voorwaardelijke expressie, zoals in het volgende voorbeeld wordt weergegeven:
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
Als u in het voorgaande voorbeeld de ??
-operator niet gebruikt, wordt numbers?.Length < 2
geëvalueerd als false
gelijk is aan numbers
.
Opmerking
De ?.
operator evalueert de linker operand niet meer dan één keer, wat garandeert dat deze niet kan worden gewijzigd naar null
nadat hij als niet-null is bevestigd.
Vanaf C# 14 is toewijzing toegestaan met een null-expressie voor voorwaardelijke toegang (?.
en ?[]
) voor verwijzingstypen. Zie bijvoorbeeld de volgende methode:
person?.FirstName = "Scott";
messages?[5] = "five";
In het voorgaande voorbeeld ziet u de toewijzing aan een eigenschap en een geïndexeerd element voor een verwijzingstype dat null kan zijn. Een belangrijke eigenschap van deze toewijzing is dat de rechterkant van =
alleen wordt geëvalueerd wanneer de linkerkant bekend is als niet-null. In de volgende code wordt de functie GenerateNextIndex
bijvoorbeeld alleen aangeroepen wanneer de values
matrix niet null is. Als de values
array null is, wordt GenerateNextIndex
niet aangeroepen.
person?.FirstName = "Scott";
messages?[5] = "five";
Met andere woorden: de voorgaande code is gelijk aan de volgende code met behulp van een if
instructie voor de null-controle:
if (values is not null)
{
values[2] = GenerateNextIndex();
}
Naast toewijzing zijn elke vorm van samengestelde toewijzing, zoals +=
of -=
, toegestaan. Verhogen (++
) en verlagen (--
) zijn echter niet toegestaan.
Deze verbetering classificeert geen voorwaardelijke null-expressie als een variabele. Het kan niet worden ref
toegewezen en kan ook niet worden toegewezen aan een ref
variabele of worden doorgegeven aan een methode als een ref
of out
argument.
Thread-veilige aanroep van gedelegeerde
Gebruik de ?.
operator om te controleren of een gemachtigde niet-null is en deze op een threadveilige manier aanroept (bijvoorbeeld wanneer u een gebeurtenis genereert), zoals in de volgende code wordt weergegeven:
PropertyChanged?.Invoke(…)
Deze code is gelijk aan de volgende code:
var handler = this.PropertyChanged;
if (handler != null)
{
handler(…);
}
Het voorgaande voorbeeld is een thread-veilige manier om ervoor te zorgen dat alleen een niet-null-waarde handler
wordt aangeroepen. Omdat gedelegeerde exemplaren onveranderbaar zijn, kan er geen thread het object wijzigen waarnaar wordt verwezen door de handler
lokale variabele. Met name als de code die door een andere thread wordt uitgevoerd, zich afmeldt voor de PropertyChanged
gebeurtenis en PropertyChanged
null
wordt voordat handler
wordt aangeroepen, blijft het object waarnaar handler
verwijst ongewijzigd.
Aanroepexpressie ()
Gebruik haakjes, ()
om een methode aan te roepen of een gemachtigde aan te roepen.
De volgende code laat zien hoe u een methode aanroept met of zonder argumenten en hoe u een gemachtigde aanroept:
Action<int> display = s => Console.WriteLine(s);
List<int> numbers =
[
10,
17
];
display(numbers.Count); // output: 2
numbers.Clear();
display(numbers.Count); // output: 0
U gebruikt ook haakjes wanneer u een constructor aanroept met de new
operator.
Andere gebruiksrechten van ()
U gebruikt ook haakjes om de volgorde aan te passen waarin bewerkingen in een expressie moeten worden geëvalueerd. Zie C#-operators voor meer informatie.
Cast-expressies, die expliciete typeconversies uitvoeren, gebruiken ook haakjes.
Index van eindoperator ^
Index- en bereikoperators kunnen worden gebruikt met een type dat kan worden geteld. Een type dat kan worden geteld is een type met een eigenschap die ofwel int
of Count
heet, met een toegankelijke Length
accessor.
Verzamelingsexpressies zijn ook afhankelijk van telbare typen.
Opmerking
Enkele dimensionale matrices kunnen worden geteld. Multidimensionale arrays zijn dat niet. De ^
operators en ..
(bereik) kunnen niet worden gebruikt in multidimensionale matrices.
De ^
operator geeft de positie van het element aan vanaf het einde van een reeks. Voor een sequentie van lengte length
, wijst ^n
naar het element met offset length - n
vanaf het begin van een sequentie. Verwijst bijvoorbeeld ^1
naar het laatste element van een reeks en ^length
verwijst naar het eerste element van een reeks.
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
Zoals in het voorgaande voorbeeld wordt weergegeven, is de expressie ^e
van het System.Index type. In expressie ^e
moet het resultaat e
impliciet converteerbaar zijn naar int
.
U kunt de ^
operator ook gebruiken met de bereikoperator om een bereik van indexen te maken. Voor meer informatie, zie Indexen en bereik.
Vanaf C# 13 kan de index van de eindoperator worden gebruikt in een object-initialisatiefunctie.
Bereikoperator ..
De ..
operator geeft het begin en einde van een reeks indexen aan als operanden. De linker operande is een inclusief begin van een bereik. De rechteroperand is een exclusief einde van een bereik. Een van de operanden kan een index zijn vanaf het begin of vanaf het einde van een reeks, zoals in het volgende voorbeeld wordt weergegeven:
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));
Zoals in het voorgaande voorbeeld wordt weergegeven, is de expressie a..b
van het System.Range type. In expressie a..b
moeten de resultaten van a
en b
impliciet worden omgezet in Int32 of Index.
Belangrijk
Impliciete conversies van int
naar Index
werpen een ArgumentOutOfRangeException wanneer de waarde negatief is.
U kunt een van de operanden van de ..
operator weglaten om een open eindbereik te verkrijgen.
-
a..
is gelijk aana..^0
-
..b
is gelijk aan0..b
-
..
is gelijk aan0..^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));
In de volgende tabel ziet u verschillende manieren om verzamelingsbereiken uit te drukken:
Uitdrukkingen voor de bereikoperator | Beschrijving |
---|---|
.. |
Alle waarden in de verzameling. |
..end |
Waarden van begin tot end exclusief. |
start.. |
Waarden inclusief vanaf start tot het einde. |
start..end |
Waarden vanaf start inclusief tot end exclusief. |
^start.. |
Waarden van start tot het einde inclusief tellen vanaf het einde. |
..^end |
Waarden vanaf het begin tot aan end , waarbij vanaf het einde exclusief wordt geteld. |
start..^end |
Waarden van start inclusief tot end exclusief, geteld vanaf het einde. |
^start..^end |
Waarden van start inclusief tot end uitsluitend beide tellen vanaf het einde. |
Het volgende voorbeeld toont het effect van het toepassen van alle reeksen die in de vorige tabel worden getoond.
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
Voor meer informatie, zie Indexen en bereik.
Het ..
token wordt ook gebruikt voor het verspreide element in een verzamelingsexpressie.
Overbelasting van operatoren
De .
, ()
, ^
en ..
operators kunnen niet worden overbelast. De []
operator wordt ook beschouwd als een niet-overbelastingsbare operator. Gebruik indexeerfuncties ter ondersteuning van indexering met door de gebruiker gedefinieerde typen.
C#-taalspecificatie
Zie de volgende secties van de C#-taalspecificatie voor meer informatie:
Voor meer informatie over indexen en bereiken, zie de notitie van het functievoorstel.