Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Számos operátor és kifejezés használatával érhet el egy típustagot. A taghozzáférési operátorok közé tartozik a taghozzáférés (.
), a tömbelem vagy az indexelő hozzáférése ([]
), a végponttól számított index (^
), a tartomány (..
), a null-feltételes operátorok (?.
és ) és ?[]
a metódushívás (()
). Ezek az operátorok közé tartoznak a null-feltételes tagok hozzáférése (?.
) és az indexelő hozzáférési (?[]
) operátorai.
-
.
(taghozzáférés): egy névtér vagy egy típus tagjának elérése -
[]
(tömbelem vagy indexelő hozzáférése): tömbelem vagy típusindexelő elérése -
?.
és?[]
(null feltételes operátorok): tag- vagy elemhozzáférési művelet végrehajtása csak akkor, ha egy operandus nem null értékű -
()
(meghívás): hozzáféréssel rendelkező metódus meghívása vagy meghatalmazott meghívása -
^
(index a végéről): annak jelzése, hogy az elem pozíciója egy sorozat végéről származik -
..
(tartomány): a sorozatelemek tartományának beolvasásához használható indextartomány megadása
Taghozzáférés kifejezése .
A .
token segítségével érhet el egy névtér vagy egy típus egy tagját, ahogy az alábbi példák mutatják:
- Beágyazott
.
névtér elérése névtéren belül, ahogy az irányelv alábbi példájausing
is mutatja:
using System.Collections.Generic;
- Használja a
.
elemet egy minősített név létrehozásához, hogy hozzáférjen egy típushoz egy névtérben, ahogyan azt az alábbi kód is mutatja:
System.Collections.Generic.IEnumerable<int> numbers = [1, 2, 3];
A using
utasítást használja, hogy a minősített nevek használata opcionális legyen.
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
.
segítségével is hozzáférhet egy bővítménymetódushoz.
Indexelő operátor []
A szögletes zárójeleket []
általában tömbök, indexelők vagy mutatóelemek elérésére használják. A C# 12-től []
kezdve egy gyűjteménykifejezést foglal magában.
Tömbhozzáférés
Az alábbi példa a tömbelemek elérését mutatja be:
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
Ha egy tömbindex kívül esik egy tömb megfelelő dimenziójának határain, akkor a függvény egy IndexOutOfRangeException értéket ad.
Ahogy az előző példában is látható, szögletes zárójeleket is használhat tömbtípus deklarálásakor vagy tömbpéldány példányosításakor.
A tömbökről további információt a Tömbök című témakörben talál.
Indexelői hozzáférés
Az alábbi példa a .NET Dictionary<TKey,TValue> típust használja az indexelő hozzáférésének szemléltetésére:
var dict = new Dictionary<string, double>();
dict["one"] = 1;
dict["pi"] = Math.PI;
Console.WriteLine(dict["one"] + dict["pi"]); // output: 4.14159265358979
Az indexelők lehetővé teszik a felhasználó által definiált típusú példányok indexelését a tömbindexeléshez hasonlóan. A tömbindexekkel ellentétben, amelyeknek egész számnak kell lenniük, az indexelő paraméterek bármilyen típusúnak deklarálhatók.
További információ az indexelőkről: Indexelők.
A [] egyéb használati módjai
A mutatóelem-hozzáféréssel kapcsolatos információkért tekintse meg a Mutatóelem-hozzáférés operátor [] szakaszát a Mutatóhoz kapcsolódó operátorok című cikkben. A gyűjteménykifejezésekkel kapcsolatos információkért tekintse meg a gyűjteménykifejezések cikkét .
Az attribútumok megadásához szögletes zárójeleket is használhat:
[System.Diagnostics.Conditional("DEBUG")]
void TraceMethod() {}
A szögletes zárójelek emellett listaminták kijelölésére is használhatók a mintaegyezéshez vagy a teszteléshez.
arr is ([1, 2, ..])
//Specifies that an array starts with (1, 2)
Null feltételes operátorok ?.
és ?[]
A null feltételes operátor csak akkor alkalmaz taghozzáférési (?.
) vagy elemhozzáférési (?[]
) műveletet az operandusra, ha az operandus nem null értékű; ellenkező esetben visszaadja a függvényt null
. Más szóval:
Ha a
a
kiértékelésenull
értékű, akkor aa?.x
vagy aa?[x]
eredménye isnull
lesz.Ha a
a
kiértékelése nem null értékű, akkor aa?.x
vagya?[x]
eredménye ugyanaz, mint aa.x
vagya[x]
eredménye, azonos sorrendben.Megjegyzés:
Ha
a.x
vagya[x]
kivesz egy kivételt,a?.x
vagya?[x]
ugyanazt a kivételt a nem nulla
értékre veti. Például, haa
egy nem null értékű tömbpéldány, ésx
kívül esik aa
határain, akkora?[x]
egy IndexOutOfRangeException-t dobna.
A null feltételes operátorok rövidzárolást jelentenek. Vagyis ha egy feltételes tag- vagy elemhozzáférési műveletlánc egyik művelete visszatér null
, a lánc többi része nem lesz végrehajtva. A következő példában B
nem kerül kiértékelésre, ha A
értéke null
. Továbbá, C
nem kerül kiértékelésre, ha A
vagy B
értéke null
.
A?.B?.Do(C);
A?.B?[C];
Ha A
lehet null, de B
és C
nem lennének null, ha A nem null, akkor csak a null-feltételes operátort kell alkalmaznia A
:
A?.B.C();
Az előző példában a B
értékelése és a C()
meghívása nem történik meg, ha a A
értéke null. Ha azonban a láncolt tag hozzáférése megszakad, például zárójelek szerint, a (A?.B).C()
rövidzárolás nem történik meg.
Az alábbi példák bemutatják a ?.
és ?[]
operátorok használatát:
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}");
}
Az első előző példa a null-egyesítő operátort ??
is használja egy alternatív kifejezés megadására, amely kiértékelhető abban az esetben, ha a null-feltételes művelet eredménye null
.
Ha a a.x
nem nullára állítható értéktípus a[x]
, akkor a T
vagy a?.x
a megfelelő a?[x]
. Ha típuskifejezésre T
van szüksége, alkalmazza a null-szenesítő operátort ??
egy null-feltételes kifejezésre, ahogyan az alábbi példa mutatja:
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
Az előző példában, ha nem használja a ??
operátort, akkor a numbers?.Length < 2
kiértékelése false
állapotában numbers
eredményez null
.
Megjegyzés:
Az ?.
operátor legfeljebb egyszer értékeli ki a bal oldali operandust, így garantálva, hogy a nem null értékűként való ellenőrzés után nem lehet módosítani null
.
A C# 14-től kezdődően a hozzárendelés a hivatkozástípusok null feltételes hozzáférési kifejezésével (?.
és ?[]
) megengedett. Lásd például a következő módszert:
person?.FirstName = "Scott";
messages?[5] = "five";
Az előző példa egy tulajdonsághoz és egy indexelt elemhez való hozzárendelést mutat be egy hivatkozástípuson, amely null értékű lehet. Ennek a hozzárendelésnek egy fontos jellemzője, hogy a =
jobb oldalán lévő kifejezés csak akkor kerül kiértékelésre, ha a bal oldali kifejezés nem null értékű. Az alábbi kódban például a függvény GenerateNextIndex
csak akkor lesz meghívva, ha a values
tömb nem null értékű. Ha a values
tömb értéke null, a GenerateNextIndex
nem kerül meghívásra.
person?.FirstName = "Scott";
messages?[5] = "five";
Más szóval az előző kód egyenértékű az alábbi kóddal, amely a null-ellenőrzésre vonatkozó utasítást if
használja:
if (values is not null)
{
values[2] = GenerateNextIndex();
}
A hozzárendelésen kívül az összetett hozzárendelések bármely formája, például +=
vagy -=
, engedélyezett. A növekmény (++
) és a decrement (--
) azonban nem engedélyezett.
Ez a fejlesztés nem sorolja be a null feltételes kifejezéseket változóként. Nem rendelhető ref
hozzá, és nem rendelhető hozzá ref
változóhoz, vagy nem adható át metódusnak ref
vagy out
argumentumként.
Szálbiztos delegált meghívás
A ?.
operátorral ellenőrizheti, hogy egy delegált nem null értékű-e, és meghívhatja szálbiztos módon (például esemény kiváltásakor), ahogyan azt az alábbi kód mutatja:
PropertyChanged?.Invoke(…)
Ez a kód egyenértékű a következő kóddal:
var handler = this.PropertyChanged;
if (handler != null)
{
handler(…);
}
Az előző példa egy szálbiztos módszer annak biztosítására, hogy csak egy nem null értékű handler
elem legyen meghívva. Mivel a delegált példányok nem módosíthatók, egyetlen szál sem módosíthatja a handler
helyi változó által hivatkozott objektumot. Különösen akkor, ha egy másik szál által futtatott kód leiratkozik az PropertyChanged
eseményről, és PropertyChanged
null
lesz, még mielőtt handler
meghívásra kerülne, az handler
által hivatkozott objektum változatlan marad.
Hívási kifejezés
Zárójelek használatával meghívhat ()
, vagy meghívhat egy meghatalmazottat.
Az alábbi kód bemutatja, hogyan hívhat meg egy metódust argumentumokkal vagy anélkül, és hogyan hívhat meg meghatalmazottat:
Action<int> display = s => Console.WriteLine(s);
List<int> numbers =
[
10,
17
];
display(numbers.Count); // output: 2
numbers.Clear();
display(numbers.Count); // output: 0
Zárójeleket is használhat, amikor konstruktort hív meg az new
operátorral.
A () egyéb használati módjai
Zárójelek használatával is módosíthatja a kifejezések műveleteinek kiértékelési sorrendjét. További információ: C# operátorok.
Az kaszt kifejezések, amelyek explicit típusú átalakítást hajtanak végre, szintén zárójeleket használnak.
Index a záró operátorból ^
Az index- és tartományoperátorok megszámlálható típussal használhatók. A megszámlálható típus egy olyan típus, amelynek van egy int
vagy Count
nevű tulajdonsága egy hozzáférhető Length
hozzáférővelget
.
A gyűjteménykifejezésekmegszámlálható típusokra is támaszkodnak.
Megjegyzés:
Az egydimenziós tömbök megszámlálhatók. A többdimenziós tömbök nem. A ^
(tartomány) operátorok ..
nem használhatók többdimenziós tömbökben.
Az ^
operátor egy sorozat végéről jelzi az elem pozícióját. A sorozat hossza length
^n
esetén a sorozat kezdetétől eltolással length - n
rendelkező elemre mutat. Például egy sorozat utolsó elemére mutat, ^1
és ^length
a sorozat első elemére mutat.
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
Ahogy az előző példa is mutatja, a kifejezés ^e
a System.Index típus. A kifejezésben ^e
az e
eredményének implicit módon konvertálhatónak kell lennie int
.
Az operátort a ^
tartomány operátorával is használhatja indextartomány létrehozásához. További információ: Indexek és tartományok.
A C# 13-tól kezdődően a záró operátor indexe használható az objektum inicializálójában.
Tartomány operátor ..
Az ..
operátor egy indextartomány kezdetét és végét adja meg operandusként. A bal oldali operandus egy tartomány befogadó kezdete. A jobb oldali operandus egy tartomány kizárólagos vége. Az operandusok bármelyike lehet index egy sorozat elejétől vagy végétől kezdve, ahogy az alábbi példa mutatja:
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));
Ahogy az előző példa is mutatja, a kifejezés a..b
a System.Range típus. A a..b
kifejezésben a a
és b
eredményeknek implicit módon konvertálhatónak kell lenniük a Int32 vagy Index típusra.
Fontos
Az int
típusú implicit konverziók Index
típusra ArgumentOutOfRangeException kivételt dobnak, ha az érték negatív.
A ..
operátor bármely operandusát kihagyhatja egy nyitott végű tartomány eléréséhez.
-
a..
egyenértékű aa..^0
-
..b
egyenértékű a0..b
-
..
egyenértékű a0..^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));
Az alábbi táblázat a gyűjteménytartományok kifejezésének különböző módjait mutatja be:
Tartomány operátorának kifejezése | Leírás |
---|---|
.. |
A gyűjtemény összes értéke. |
..end |
Értékek az elejétől a end kizárólagosig. |
start.. |
Értékek a start -t beleértve a végéig. |
start..end |
Értékek a start befogadótól a end kizárólagosig. |
^start.. |
Értékek a start ponttól kezdődően a végéig, a végétől számítva. |
..^end |
Értékek a kezdetektől a end -ig, kizárólag a végétől visszaszámlálva. |
start..^end |
Értékek start -tól bezárólag egészen end -ig kizárólag, a végéről számolva. |
^start..^end |
Értékek start -tól beleértve end kizárva, mindkettő a végétől számítva. |
Az alábbi példa az előző táblázatban bemutatott összes tartomány használatának hatását mutatja be:
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
További információ: Indexek és tartományok.
A ..
token arra is használható, hogy bővítse egy gyűjteménykifejezés kiterjesztési elemét.
Operátorok túlterhelése
A .
, ()
, ^
és ..
operátorok nem terhelhetők túl. Az []
operátort nem túlterhelhető operátornak is tekintik. Az indexelők segítségével támogathatja a felhasználó által definiált típusok indexelését.
C# nyelvspecifikáció
További információt a C# nyelvspecifikációjának alábbi szakaszaiban talál:
Az indexekkel és tartományokkal kapcsolatos további információkért tekintse meg a funkciójavaslat megjegyzését.