Bővítménymetelyek implementálása egy osztályhoz

Befejeződött

Á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 a using 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.