Menerapkan metode ekstensi untuk kelas
Biasanya, ada dua cara untuk menambahkan metode ke jenis yang ada:
- Ubah kode sumber untuk jenis tersebut. Memodifikasi sumber membuat perubahan yang melanggar jika Anda juga menambahkan bidang data privat untuk mendukung metode .
- Tentukan metode baru dalam kelas turunan. Metode tidak dapat ditambahkan dengan cara ini menggunakan pewarisan untuk jenis lain, seperti struktur dan enumerasi. Juga tidak dapat digunakan untuk "menambahkan" metode ke kelas yang disegel.
Metode ekstensi memungkinkan Anda "menambahkan" metode ke jenis yang ada tanpa memodifikasi jenis itu sendiri atau menerapkan metode baru dalam jenis yang diwariskan. Metode ekstensi juga tidak harus berada di rakitan yang sama dengan jenis yang diperluasnya. Anda memanggil metode ekstensi seolah-olah itu adalah anggota jenis yang ditentukan.
Metode ekstensi
Metode ekstensi memungkinkan Anda untuk "menambahkan" metode ke jenis yang ada tanpa membuat jenis turunan baru, kompilasi ulang, atau memodifikasi jenis asli. Metode ekstensi adalah metode statis, tetapi dipanggil seolah-olah metode instans pada jenis yang diperluas. Untuk kode klien yang ditulis dalam C#, F# dan Visual Basic, tidak ada perbedaan yang jelas antara memanggil metode ekstensi dan metode yang ditentukan dalam jenis.
Mengikat metode ekstensi pada waktu kompilasi
Anda dapat menggunakan metode ekstensi untuk memperluas kelas atau antarmuka, tetapi tidak untuk mengambil alihnya. Metode ekstensi dengan nama dan tanda tangan yang sama dengan metode kelas tidak pernah dipanggil. Pada waktu kompilasi, metode ekstensi selalu memiliki prioritas yang lebih rendah daripada metode instans yang ditentukan dalam jenis itu sendiri. Dengan kata lain, jika jenis memiliki metode bernama Process(int i), dan Anda memiliki metode ekstensi dengan tanda tangan yang sama, pengkompilasi selalu mengikat ke metode instans. Ketika kompilator menemukan pemanggilan metode, ia mencari kecocokan dalam metode instans jenis. Jika tidak ada metode instans yang cocok yang ditemukan, pengkompilasi mencari metode ekstensi apa pun yang ditentukan untuk jenis tersebut. Pengkompilasi mengikat ke metode ekstensi pertama yang ditemukannya.
Contoh berikut menunjukkan aturan yang diikuti pengkompilasi C# dalam menentukan apakah akan mengikat panggilan metode ke metode instans pada jenis, atau ke metode ekstensi.
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.
Dalam contoh ini, kelas Person memiliki tiga properti: FirstName, LastName, dan Age. Kelas Person juga memiliki metode instans Introduce yang menulis pesan ke konsol.
Kelas PersonExtensions menentukan metode ekstensi untuk kelas Person. Kelas PersonExtensions berisi metode ekstensi berikut:
-
DisplayFullName: Menulis nama lengkap orang tersebut ke konsol. -
IsAdult: Mengembalikan nilai Boolean yang menunjukkan apakah orang tersebut sudah dewasa. -
Introduce: Menulis pesan ke konsol. Metode ini memiliki dua kelebihan beban: satu tanpa parameter dan satu dengan parameter string. -
Introduce(this Person person, string greeting): Menulis pesan ke konsol dengan salam kustom. -
Introduce(): Menulis pesan default ke konsol.
Metode Main membuat dua instans kelas Person dan memanggil metode Introduce pada setiap instans. Metode Introduce yang ditentukan dalam kelas Person dijalankan. Metode Introduce tanpa parameter di kelas PersonExtensions tidak dipanggil karena kelas Person sudah memiliki metode instans Introduce dengan tanda tangan yang sama. Pengkompilasi mengikuti aturan untuk mengikat metode ekstensi pada waktu kompilasi dan memberikan prioritas pada metode instans yang ditentukan dalam jenis itu sendiri. Metode Main juga memanggil metode ekstensi DisplayFullName, IsAdult, dan metode Introduce yang kelebihan beban dengan salam kustom. Metode ekstensi dijalankan seperti yang diharapkan.
Pedoman umum
Metode ekstensi adalah opsi penting untuk membuat fungsionalitas yang dapat digunakan kembali di seluruh ekosistem .NET. Namun, memodifikasi kode objek atau mendapatkan jenis baru setiap kali masuk akal dan mungkin untuk melakukannya, masih dianggap lebih disukai. Metode ekstensi adalah pilihan yang sangat baik ketika sumber asli tidak berada di bawah kontrol Anda, ketika objek turunan tidak pantas atau tidak mungkin, atau ketika fungsionalitas tidak boleh diekspos di luar cakupan yang berlaku.
Saat menggunakan metode ekstensi untuk memperluas jenis yang kode sumbernya tidak Anda kendalikan, Anda menjalankan risiko bahwa perubahan dalam implementasi jenis akan menyebabkan metode ekstensi Anda rusak. Jika Anda menerapkan metode ekstensi untuk jenis tertentu, ingat poin-poin berikut:
- Metode ekstensi tidak dipanggil jika memiliki tanda tangan yang sama dengan metode yang ditentukan dalam jenis .
- Metode ekstensi dibawa ke dalam cakupan di tingkat namespace. Misalnya, jika Anda memiliki beberapa kelas statis yang berisi metode ekstensi dalam satu namespace bernama
Extensions, semuanya akan dibawa ke dalam cakupan oleh arahanusing Extensions;.
Untuk pustaka kelas yang Anda terapkan, Anda tidak boleh menggunakan metode ekstensi untuk menghindari penambahan nomor versi rakitan. Jika Anda ingin menambahkan fungsionalitas signifikan ke pustaka tempat Anda memiliki kode sumber, ikuti panduan .NET untuk penerapan versi rakitan.