Bővítménymetelyek implementálása egy osztályhoz
Általában kétféleképpen adhat hozzá metódust egy meglévő típushoz:
- Módosítsa az adott típus forráskódját. A forrás módosítása kompatibilitástörő változást hoz létre, ha bármilyen privát adatmezőt is hozzáad a metódus támogatásához.
- Definiálja az új metódust egy származtatott osztályban. Más típusú, például struktúrák és enumerálások öröklésével nem adható hozzá metódus. Arra sem használható, hogy metódust "adjon hozzá" egy lezárt osztályhoz.
A bővítménymetódusok lehetővé teszik egy metódus meglévő típushoz való hozzáadását anélkül, hogy módosítaná magát a típust, vagy öröklött típusban implementálaná az új metódust. A bővítménymetódusnak nem kell ugyanabban a szerelvényben tartózkodnia, mint a kiterjesztett típus. Úgy hívhat meg egy bővítménymetódust, mintha egy adott típus meghatározott tagja lenne.
Bővítménymetelyek
A bővítménymetelyek lehetővé teszik, hogy új származtatott típus létrehozása, újrafordítás vagy az eredeti típus egyéb módosítása nélkül "hozzáadja" a metódusokat a meglévő típusokhoz. A bővítménymetelyek statikus metódusok, de úgy hívják őket, mintha a kiterjesztett típushoz tartozó példánymetodusok lennének. A C#, F# és Visual Basic nyelven írt ügyfélkódok esetében nincs nyilvánvaló különbség a bővítménymetódus meghívása és a típusban definiált metódusok között.
Kötéskiterjesztési módszerek fordításkor
A bővítménymetelyekkel kiterjeszthet egy osztályt vagy felületet, de nem bírálhatja felül őket. Az osztálymetódus nevével és aláírásával megegyező kiterjesztési metódus soha nem lesz meghívva. Fordításkor a bővítménymetelyek mindig alacsonyabb prioritással rendelkeznek, mint a típusban definiált példánymetelyek. Más szóval, ha egy típus Process(int i)nevű metódussal rendelkezik, és ugyanazzal az aláírással rendelkező bővítménymetódussal rendelkezik, a fordító mindig a példánymetódushoz kapcsolódik. Amikor a fordító metódushívással találkozik, egyezést keres a típus példánymetódusaiban. Ha nem található egyező példánymetódus, a fordító megkeresi a típushoz definiált bővítménymetódusokat. A fordító a talált első bővítménymetódushoz kapcsolódik.
Az alábbi példa azokat a szabályokat mutatja be, amelyeket a C#-fordító követ annak meghatározásához, hogy a metódushívást egy példánymetódushoz vagy egy bővítménymetódushoz kell-e kötni.
namespace ExtensionMethodDemo.PersonNamespace
{
// Define a simple class with properties and methods
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public void Introduce()
{
Console.WriteLine($"Hi, I'm {FirstName} {LastName}, and I'm {Age} years old.");
}
}
}
namespace ExtensionMethodDemo.PersonExtensionsNamespace
{
using ExtensionMethodDemo.PersonNamespace;
// Define an extension method for the Person class
public static class PersonExtensions
{
public static void DisplayFullName(this Person person)
{
Console.WriteLine($"Full Name: {person.FirstName} {person.LastName}");
}
public static bool IsAdult(this Person person)
{
return person.Age >= 18;
}
public static void Introduce()
{
Console.WriteLine($"Extension - Hi, it's nice to meet you.");
}
// Extension method attempting to override Introduce
public static void Introduce(this Person person, string greeting)
{
Console.WriteLine($"{greeting}, I'm {person.FirstName} {person.LastName}, and I'm {person.Age} years old.");
}
}
}
namespace ExtensionMethodDemo
{
using ExtensionMethodDemo.PersonNamespace;
using ExtensionMethodDemo.PersonExtensionsNamespace;
class Program
{
static void Main(string[] args)
{
// Create instances of the Person class
Person person1 = new Person { FirstName = "FName1", LastName = "LName1", Age = 25 };
Person person2 = new Person { FirstName = "FName2", LastName = "LName2", Age = 16 };
// Use the methods of the Person class
person1.Introduce();
person2.Introduce();
// Use the extension methods
person1.DisplayFullName();
Console.WriteLine($"Is {person1.FirstName} an adult? {person1.IsAdult()}");
person2.DisplayFullName();
Console.WriteLine($"Is {person2.FirstName} an adult? {person2.IsAdult()}");
// Use the extension method that attempts to override Introduce
person1.Introduce("Hello");
person2.Introduce("Greetings");
}
}
}
// Output:
// Hi, I'm FName1 LName1, and I'm 25 years old.
// Hi, I'm FName2 LName2, and I'm 16 years old.
// Full Name: FName1 LName1
// Is FName1 an adult? True
// Full Name: FName2 LName2
// Is FName2 an adult? False
// Hello, I'm FName1 LName1, and I'm 25 years old.
// Greetings, I'm FName2 LName2, and I'm 16 years old.
Ebben a példában a Person osztály három tulajdonsággal rendelkezik: FirstName, LastNameés Age. A Person osztály egy példánymetódussal is rendelkezik, Introduce, amely üzenetet ír a konzolra.
A PersonExtensions osztály a Person osztály bővítménymetóráit határozza meg. A PersonExtensions osztály a következő bővítménymetszeteket tartalmazza:
-
DisplayFullName: A személy teljes nevét írja a konzolra. -
IsAdult: Logikai értéket ad vissza, amely azt jelzi, hogy a személy felnőtt-e. -
Introduce: Üzenetet ír a konzolra. Ez a metódus két túlterheléssel rendelkezik: egy paraméter nélkül, egy pedig egy sztringparaméterrel. -
Introduce(this Person person, string greeting): Üzenet írása a konzolra egyéni üdvözléssel. -
Introduce(): Alapértelmezett üzenetet ír a konzolra.
A Main metódus két példányt hoz létre a Person osztályból, és meghívja a Introduce metódust minden példányon. A Introduce osztályban definiált Person metódus végrehajtása történik. A Introduce osztályban paraméterek nélküli PersonExtensions metódust a Person osztály már rendelkezik ugyanazzal az aláírással Introduce példánymetódussal. A fordító a kötéskiterjesztési módszerekre vonatkozó szabályokat követi fordításkor, és prioritást ad a típusban meghatározott példánymetódusnak. A Main metódus egyéni üdvözléssel meghívja a bővítménymetódusokat DisplayFullName, IsAdultés a túlterhelt Introduce metódust is. A bővítménymetelyek a várt módon lesznek végrehajtva.
Általános irányelvek
A bővítménymetelyek fontos lehetőséget jelentenek az újrafelhasználható funkciók létrehozására a .NET-ökoszisztémában. Az objektum kódjának módosítása vagy egy új típus származtatása azonban mindig előnyösebbnek számít, ha ésszerű és lehetséges. A bővítménymetódusok kiváló választásnak minősülnek, ha az eredeti forrás nincs az Ön felügyelete alatt, ha egy származtatott objektum nem megfelelő vagy lehetetlen, vagy ha a funkciónak nem szabad a megfelelő hatókörön kívülre kerülnie.
Ha bővítménymetódusokat használ egy olyan típus kiterjesztéséhez, amelynek forráskódját nem ön felügyeli, fennáll annak a kockázata, hogy a típus implementációjának változása a bővítménymetódus megszakadását okozza. Ha egy adott típushoz bővítménymetó módszereket implementál, jegyezze meg a következő pontokat:
- A bővítménymetódus nem hívható meg, ha ugyanazzal az aláírással rendelkezik, mint a típusban definiált metódus.
- A bővítménymetelyek a névtér szintjén kerülnek hatókörbe. Ha például több olyan statikus osztálya van, amely
Extensionsnevű egyetlen névtérben tartalmaz bővítménymetszeteket, azokat ausing Extensions;irányelv fogja hatókörbe helyezni.
Az ön által implementált osztálytárak esetében ne használjon bővítménymetelyeket a szerelvény verziószámának növelésének elkerülése érdekében. Ha jelentős funkciókat szeretne hozzáadni egy olyan kódtárhoz, amelynek a forráskódja a tulajdonosa, kövesse a .NET szerelvény-verziószámozásra vonatkozó irányelveit.