Share via


System.Delegate és a delegate kulcsszó

Előző

Ez a cikk a meghatalmazottakat támogató .NET-osztályokról és arról, hogy ezek hogyan vannak megfeleltetve a delegate kulcsszónak.

Delegálttípusok definiálása

Kezdjük a "delegálás" kulcsszóval, mert elsősorban ezt fogja használni a meghatalmazottak használata során. A fordító által a kulcsszó használatakor létrehozott kód megfelelteti a delegate metódushívásokat, amelyek meghívják az osztályok és MulticastDelegate az osztályok tagjaitDelegate.

Meghatalmazási típust a metódusadák definiálásához hasonló szintaxissal definiálhat. Csak adja hozzá a delegate kulcsszót a definícióhoz.

Továbbra is a List.Sort() metódust használjuk példaként. Az első lépés egy típus létrehozása az összehasonlító meghatalmazott számára:

// From the .NET Core library

// Define the delegate type:
public delegate int Comparison<in T>(T left, T right);

A fordító létrehoz egy osztályt, amely a System.Delegate használt aláírással egyezik (ebben az esetben egy egész számot visszaadó metódus, amelynek két argumentuma van). Ennek a meghatalmazottnak a típusa.Comparison A Comparison meghatalmazott típusa általános típus. Az általános adatokkal kapcsolatos részletekért lásd itt.

Figyelje meg, hogy a szintaxis úgy tűnhet, mintha egy változót deklarál, de valójában egy típust deklarál. Delegálttípusokat definiálhat osztályokon belül, közvetlenül a névtereken belül, vagy akár a globális névtérben is.

Feljegyzés

Nem ajánlott deklarálni a delegált típusokat (vagy más típusokat) közvetlenül a globális névtérben.

A fordító emellett hozzáadja és eltávolítja az ehhez az új típushoz tartozó kezelőket, hogy az osztály ügyfelei metódusokat vegyenek fel és távolítsanak el egy példány meghívási listájából. A fordító kikényszeríti, hogy a hozzáadott vagy eltávolított metódus aláírása megegyezik a metódus deklarálásakor használt aláírással.

Meghatalmazottpéldányok deklarálása

A meghatalmazott definiálása után létrehozhat egy ilyen típusú példányt. A C#-ban lévő összes változóhoz hasonlóan a delegált példányokat sem közvetlenül névtérben, sem globális névtérben nem deklarálhatja.

// inside a class definition:

// Declare an instance of that type:
public Comparison<T> comparator;

A változó típusa a Comparison<T>korábban definiált delegálási típus. A változó neve .comparator

A fenti kódrészlet tagváltozót deklarált egy osztályon belül. Deklarálhat delegált változókat is, amelyek helyi változók, vagy argumentumok a metódusokhoz.

Meghatalmazottak meghívása

A meghatalmazott meghívási listájában szereplő metódusokat a meghatalmazott meghívásával hívhatja meg. A metóduson belül a Sort() kód meghívja az összehasonlító metódust az objektumok elhelyezésének sorrendjének meghatározásához:

int result = comparator(left, right);

A fenti sorban a kód meghívja a meghatalmazotthoz csatolt metódust. A változót metódusnévként kezeli, és normál metódushívási szintaxissal hívja meg.

Ez a kódsor nem biztonságos feltételezés: Nincs garancia arra, hogy a delegálthoz hozzáadtak egy célt. Ha nem csatoltak célokat, a fenti sor dobást okozna NullReferenceException . A probléma megoldásához használt kifejezések bonyolultabbak, mint egy egyszerű null-ellenőrzés, és a sorozat későbbi részében szerepelnek.

Meghívási célok hozzárendelése, hozzáadása és eltávolítása

Így van definiálva egy delegálttípus, valamint a delegált példányok deklarálása és meghívása.

A metódust használni List.Sort() kívánó fejlesztőknek meg kell határozniuk egy metódust, amelynek aláírása megegyezik a delegált típusdefinícióval, és hozzá kell rendelni a rendezési módszer által használt delegálthoz. Ez a hozzárendelés hozzáadja a metódust a delegált objektum meghívási listájához.

Tegyük fel, hogy a sztringek listáját a hosszuk szerint szeretné rendezni. Az összehasonlító függvény a következő lehet:

private static int CompareLength(string left, string right) =>
    left.Length.CompareTo(right.Length);

A metódus privát metódusként van deklarálva. Ez rendben van. Előfordulhat, hogy nem szeretné, hogy ez a módszer a nyilvános felület része legyen. Delegálthoz csatolva továbbra is használható összehasonlítási módszerként. A hívó kód ezt a metódust csatolja a delegált objektum céllistájához, és ezen a meghatalmazotton keresztül érheti el.

Ezt a kapcsolatot úgy hozhatja létre, hogy átadja ezt a metódust a List.Sort() metódusnak:

phrases.Sort(CompareLength);

Figyelje meg, hogy a metódus nevét zárójelek nélkül használja a rendszer. A metódus argumentumként való használata arra utasítja a fordítót, hogy konvertálja a metódushivatkozást egy delegált meghívási célként használható hivatkozássá, és ezt a metódust hívási célként csatolja.

Egy típusváltozó Comparison<string> deklarálásával és egy hozzárendeléssel is explicit lehetett volna:

Comparison<string> comparer = CompareLength;
phrases.Sort(comparer);

Azokban a használatokban, ahol a delegált célként használt metódus egy kis metódus, gyakori, hogy lambda kifejezésszintaxissal hajtja végre a hozzárendelést:

Comparison<string> comparer = (left, right) => left.Length.CompareTo(right.Length);
phrases.Sort(comparer);

A lambda-kifejezések delegált célokhoz való használatát egy későbbi szakasz ismerteti.

A Rendezés() példa általában egyetlen célmetódust csatol a meghatalmazotthoz. A delegált objektumok azonban támogatják a delegált objektumhoz több célmetódussal rendelkező meghívási listákat.

Delegált és csoportos küldésűdelegate osztályok

A fent ismertetett nyelvi támogatás biztosítja azokat a funkciókat és támogatást, amelyeket általában a meghatalmazottakkal kell dolgoznia. Ezek a funkciók a .NET Core keretrendszer két osztályára épülnek: Delegate és MulticastDelegate.

Az System.Delegate osztály és annak egyetlen közvetlen alosztálya System.MulticastDelegatebiztosítja a keretrendszer támogatását a meghatalmazottak létrehozásához, a metódusok delegált célként való regisztrálásához és a delegált célként regisztrált összes metódus meghívásához.

Érdekes, hogy az osztályok és System.MulticastDelegate az System.Delegate osztályok maguk nem delegált típusok. Ezek biztosítják az összes konkrét delegálttípus alapjait. Ugyanez a nyelvi tervezési folyamat előírta, hogy nem deklarálhat egy osztályt, amely származik Delegate vagy MulticastDelegate. A C#-nyelvi szabályok tiltják.

Ehelyett a C#-fordító létrehozza a C# nyelv kulcsszóval deklarált deklarált típusokból származtatott MulticastDelegate osztálypéldányokat.

Ez a kialakítás a C# és a .NET első kiadásában gyökerezik. A tervezőcsapat egyik célja annak biztosítása volt, hogy a nyelv megkövetelje a típusbiztonságot a meghatalmazottak használata során. Ez azt jelentette, hogy a meghatalmazottak a megfelelő típusú és számú argumentummal legyenek meghívva. És hogy minden visszatérési típus helyesen lett jelezve a fordításkor. A meghatalmazottak az 1.0 .NET-kiadás részét képezték, amely az általános verziók előtt volt.

Az ilyen típusú biztonság érvényesítésének legjobb módja az volt, hogy a fordító létrehozza azokat a konkrét delegált osztályokat, amelyek a használt metódus-aláírást képviselték.

Annak ellenére, hogy közvetlenül nem hozhat létre származtatott osztályokat, az ezekben az osztályokban definiált metódusokat fogja használni. Tekintsük át a meghatalmazottak használatakor használt leggyakoribb módszereket.

Az első, legfontosabb, hogy ne feledje, hogy minden meghatalmazott, akivel dolgozik, a forrásból MulticastDelegateszármazik. A csoportos küldési meghatalmazott azt jelenti, hogy egy meghatalmazotton keresztül történő meghíváskor több metóduscél is meghívható. Az eredeti kialakítás különbséget tett a meghatalmazottak között, ahol csak egy célmetódus csatolható és hívható meg, valamint olyan meghatalmazottak között, ahol több célmetódus is csatolható és meghívható. Ez a különbség a gyakorlatban kevésbé volt hasznos, mint eredetileg gondolták. A két különböző osztály már létrejött, és a kezdeti nyilvános kiadás óta a keretrendszerben van.

A meghatalmazottak által leggyakrabban használt metódusok a következők Invoke() : és BeginInvoke() / EndInvoke(). Invoke() meghívja az adott meghatalmazott példányhoz csatolt összes metódust. Ahogy fentebb láthatta, általában a delegált változó metódushívási szintaxisával hív meg meghatalmazottakat. Ahogy a sorozat későbbi részében látni fogja, vannak olyan minták, amelyek közvetlenül ezekkel a módszerekkel működnek.

Most, hogy megismerte a nyelvi szintaxist és azokat az osztályokat, amelyek támogatják a meghatalmazottakat, vizsgáljuk meg, hogy milyen erősen gépelt meghatalmazottakat használunk, hozunk létre és hívunk meg.

Következő