Taghozzáférési operátorok és kifejezések – a pont, az indexelő és a meghívási operátor.
Számos operátor és kifejezés használatával érhet el egy típustagot. Ezek az 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 közé tartoznak a null-feltételes taghozzáférés (?.
) é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 jogkivonattal .
egy névtér vagy egy típus egy tagját érheti el, ahogy az alábbi példák is 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;
- Minősített
.
név létrehozásához használjon egy névtéren belüli típust, ahogyan az az alábbi kódban is látható:
System.Collections.Generic.IEnumerable<int> numbers = [1, 2, 3];
using
A minősített nevek használata nem kötelező.
- A típustagok statikus és nem statikus elérésére használható
.
, ahogy az alábbi kód is mutatja:
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
Bővítménymetódushoz is .
hozzáférhet.
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.
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.
Az attribútumok megadásához szögletes zárójeleket is használhat:
[System.Diagnostics.Conditional("DEBUG")]
void TraceMethod() {}
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énytnull
.?.
Tehát:
Ha
a
a kiértékelés eredményenull
vagy eredményea?.x
a?[x]
.null
Ha
a
a kiértékelés nem null értékű, akkor az eredmény vagy annak eredményea.x
a?.x
a?[x]
a[x]
megegyezik.Feljegyzés
Ha
a.x
vagya[x]
kivesz egy kivételt,a?.x
vagya?[x]
ugyanazt a kivételt a nem nulla
értékre veti. Ha példáula
egy nem null értékű tömbpéldány, ésx
kívül esik a határána
,a?[x]
akkor a függvény egy IndexOutOfRangeException.
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 a kiértékelés nem történik meg, B
ha a kiértékelés C
null
B
A
null
eredménye a következő:A
A?.B?.Do(C);
A?.B?[C];
Ha A
lehet null, de B
C
nem lenne null, ha az A nem null, csak a null-feltételes operátort kell alkalmaznia a következőre A
:
A?.B.C();
Az előző példában a függvény nem értékeli ki a függvényt, B
és C()
nem hívja meg, ha A
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 az operátorok és ?[]
az ?.
operátorok használatát mutatják be:
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 előző két példa közül az első a null-szenesí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.x
nem null értékűT
, a?.x
vagy a?[x]
a megfelelő null értékű.T?
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 az operátort ??
, kiértékeli, numbers?.Length < 2
hogy false
mikor numbers
van null
.
Feljegyzés
Az ?.
operátor legfeljebb egyszer értékeli ki a bal oldali operandusát, garantálva, hogy nem módosítható null
a nem null értékűként való ellenőrzés után.
A null feltételes tag hozzáférési operátorát ?.
Elvis operátornak is nevezik.
Szálbiztos delegálás
?.
Az operátorral ellenőrizheti, hogy egy meghatalmazott nem null értékű-e, és meghívja-e szálbiztos módon (például esemény létrehozásakor), ahogyan 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 handler
értékű hívás 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 végrehajtott kód leiratkozik az PropertyChanged
eseményről, és PropertyChanged
null
a rendszer meghívja handler
, az általa handler
hivatkozott objektumot nem érinti.
Invocation expression ()
Zárójelek használatával meghívhat egy metódust, vagy meghívhat egy meghatalmazottat. ()
Az alábbi példa 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 explicit típusú átalakításokat végző öntött kifejezések zárójeleket is 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 vagy egy akadálymentes get
tartozéka van, vagy Length
elnevezett Count
tulajdonsággal rendelkezikint
. A gyűjteménykifejezések megszámlálható típusokra is támaszkodnak.
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 eredménynek e
implicit módon konvertálhatónak int
kell lennie .
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átora ..
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 kifejezésben a..b
az eredménynek a
b
implicit módon konvertálhatónak kell lennie a következőre Int32 : vagy Index.
Fontos
Implicit konverziók a int
negatív értéktől a dobásig Index
ArgumentOutOfRangeException .
Az operátor bármelyik operandusát ..
kihagyhatja egy nyitott végű tartomány beszerzé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 befogadótól a végéig. |
start..end |
Értékek a start befogadótól a end kizárólagosig. |
^start.. |
Értékek a start befogadótól a végéig, a végétől számítva. |
..^end |
Értékek a kezdetektől a end kizárólagos számlálásig a végétől kezdve. |
start..^end |
Értékek a befogadótól start a end kizárólagos számlálásig a végétől kezdve. |
^start..^end |
Értékek a befogadótól start a end kizárólagos számlálásig a végétől kezdve. |
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 ..
rendszer a jogkivonatot a gyűjteménykifejezések oldalpár-operátoraként is használja.
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.
Lásd még
Visszajelzés
https://aka.ms/ContentUserFeedback.
Hamarosan elérhető: 2024-ben fokozatosan kivezetjük a GitHub-problémákat a tartalom visszajelzési mechanizmusaként, és lecseréljük egy új visszajelzési rendszerre. További információ:Visszajelzés küldése és megtekintése a következőhöz: