Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Uzantı yöntemleri, geliştiricilerin yeni türetilmiş bir tür oluşturmadan önceden tanımlanmış olan veri türlerine özel işlevler eklemesini sağlar. Uzantı yöntemleri, mevcut türün örnek yöntemiymiş gibi çağrılabilecek bir yöntem yazmayı mümkün hale getirir.
Açıklamalar
Uzantı yöntemi yalnızca bir Sub
yordam veya Function
yordam olabilir. Uzantı özelliği, alanı veya olayı tanımlayamazsınız. Tüm uzantı yöntemleri ad alanından uzantı özniteliğiyle <Extension>
System.Runtime.CompilerServices işaretlenmeli ve bir Modülde tanımlanmalıdır. Bir uzantı yöntemi bir modülün dışında tanımlanırsa, Visual Basic derleyicisi "Uzantı yöntemleri yalnızca modüllerde tanımlanabilir" hata BC36551 oluşturur.
Uzantı yöntemi tanımındaki ilk parametre, yöntemin hangi veri türünü genişletir belirtir. yöntemi çalıştırıldığında, ilk parametre yöntemi çağıran veri türünün örneğine bağlıdır.
Extension
Özniteliği yalnızca bir Visual Basic Module
, Sub
veya Function
öğesine uygulanabilir. Bunu bir Class
veya Structure
öğesine uygularsanız, Visual Basic derleyicisi hata BC36550 oluşturur: "'Uzantı' özniteliği yalnızca 'Module', 'Sub' veya 'Fonksiyon' bildirimlerine uygulanabilir".
Örnek
Aşağıdaki örnek, Print
veri türüne bir String uzantısı tanımlar. Yöntem, bir dizeyi görüntülemek için Console.WriteLine
kullanır.
Print
yönteminin parametresi, aString
yönteminin, String sınıfını genişlettiğini belirtir.
Imports System.Runtime.CompilerServices
Module StringExtensions
<Extension()>
Public Sub Print(ByVal aString As String)
Console.WriteLine(aString)
End Sub
End Module
Uzantı yöntemi tanımının uzantı özniteliğiyle <Extension()>
işaretlendiğini fark edin. Yöntemin tanımlandığı modülün işaretlenmesi isteğe bağlıdır, ancak her uzantı yönteminin işaretlenmesi gerekir.
System.Runtime.CompilerServices uzantı özniteliğine erişmek için içeri aktarılmalıdır.
Uzantı yöntemleri yalnızca modüller içinde bildirilebilir. Genellikle, bir uzantı yönteminin tanımlandığı modül, çağrıldığı modülle aynı modül değildir. Bunun yerine, uzantı yöntemini içeren modül, ihtiyaç duyulursa kapsam içine almak için içe aktarılır.
Print
içeren modül kapsam dahilinde olduktan sonra, yöntem bağımsız değişken içermeyen sıradan bir örnek yöntemiymiş gibi ToUpper
çağrılabilir.
Module Class1
Sub Main()
Dim example As String = "Hello"
' Call to extension method Print.
example.Print()
' Call to instance method ToUpper.
example.ToUpper()
example.ToUpper.Print()
End Sub
End Module
Sonraki örnek, PrintAndPunctuate
, bu kez iki parametreyle tanımlanan String uzantısına bir örnektir. İlk parametre, aString
, uzantı yönteminin String tarafından genişletildiğini ortaya koyar. İkinci parametre olan punc
, yöntemi çağrıldığında bağımsız değişken olarak geçirilen bir noktalama işaretleri dizesi olması amaçlanmıştır. yöntemi, dizeyi ve ardından noktalama işaretlerini görüntüler.
<Extension()>
Public Sub PrintAndPunctuate(ByVal aString As String,
ByVal punc As String)
Console.WriteLine(aString & punc)
End Sub
Bu yöntem, punc
için bir dize bağımsız değişkeni göndererek çağrılır: example.PrintAndPunctuate(".")
Aşağıdaki örnek, Print
ve PrintAndPunctuate
'in tanımlandığını ve çağrıldığını göstermektedir.
System.Runtime.CompilerServices uzantı özniteliğine erişimi etkinleştirmek için tanım modülünde içeri aktarılır.
Imports System.Runtime.CompilerServices
Module StringExtensions
<Extension()>
Public Sub Print(aString As String)
Console.WriteLine(aString)
End Sub
<Extension()>
Public Sub PrintAndPunctuate(aString As String, punc As String)
Console.WriteLine(aString & punc)
End Sub
End Module
Daha sonra uzantı yöntemleri kapsama alınır ve şu şekilde çağrılır:
Imports ConsoleApplication2.StringExtensions
Module Module1
Sub Main()
Dim example As String = "Example string"
example.Print()
example = "Hello"
example.PrintAndPunctuate(".")
example.PrintAndPunctuate("!!!!")
End Sub
End Module
Bu veya benzer uzantı yöntemlerini çalıştırabilmek için gereken tek şey kapsam dahilinde olmalarıdır. Uzantı yöntemi içeren modül kapsam dahilindeyse IntelliSense'te görünür ve sıradan bir örnek yöntemiymiş gibi çağrılabilir.
Yöntemler çağrıldığında, ilk parametre için hiçbir bağımsız değişken gönderilmediğini fark edin. Önceki yöntem tanımlarındaki aString
parametresi, onları çağıran example
örneğine bağlı olan String
ile ilişkilidir. Derleyici, example
'yi ilk parametreye gönderilen bağımsız değişken olarak kullanacaktır.
olarak ayarlanmış Nothing
bir nesne için bir uzantı yöntemi çağrılırsa, uzantı yöntemi yürütülür. Bu normal örnek yöntemleri için geçerli değildir. Uzantı yönteminde Nothing
için açıkça kontrol edebilirsiniz.
Genişletilebilen türler
Aşağıdakiler de dahil olmak üzere Visual Basic parametre listesinde temsil edilebilen çoğu türde bir uzantı yöntemi tanımlayabilirsiniz:
- Sınıflar (referans türleri)
- Yapılar (değer türleri)
- Arayüzler
- Temsilciler
- ByRef ve ByVal bağımsız değişkenleri
- Genel yöntem parametreleri
- Diziler
İlk parametre uzantı yönteminin genişletildiği veri türünü belirttiğinden gereklidir ve isteğe bağlı olamaz. Bu nedenle, Optional
parametreler ve ParamArray
parametreler parametre listesindeki ilk parametre olamaz.
Uzantı yöntemleri geç bağlamada dikkate alınmaz.
anObject.PrintMe()
ifadeleri aşağıdaki örnekte bir MissingMemberException istisnası oluşturur ki bu, ikinci PrintMe
uzantı yöntemi tanımı silinirse göreceğiniz istisnadır.
Option Strict Off
Imports System.Runtime.CompilerServices
Module Module4
Sub Main()
Dim aString As String = "Initial value for aString"
aString.PrintMe()
Dim anObject As Object = "Initial value for anObject"
' The following statement causes a run-time error when Option
' Strict is off, and a compiler error when Option Strict is on.
'anObject.PrintMe()
End Sub
<Extension()>
Public Sub PrintMe(ByVal str As String)
Console.WriteLine(str)
End Sub
<Extension()>
Public Sub PrintMe(ByVal obj As Object)
Console.WriteLine(obj)
End Sub
End Module
En iyi yöntemler
Uzantı yöntemleri, mevcut bir türü genişletmek için kullanışlı ve güçlü bir yol sağlar. Ancak, bunları başarıyla kullanmak için dikkate alınması gereken bazı noktalar vardır. Bu konular temel olarak sınıf kitaplıklarının yazarları için geçerlidir, ancak uzantı yöntemlerini kullanan tüm uygulamaları etkileyebilir.
Genellikle, sahip olmadığınız türlere eklediğiniz uzantı yöntemleri, denetlediğiniz türlere eklenen uzantı yöntemlerinden daha savunmasızdır. Sahip olmadığınız sınıflarda uzantı yöntemlerinizi engelleyebilecek çeşitli şeyler oluşabilir.
Erişilebilir herhangi bir örnek üye, çağırma deyimindeki bağımsız değişkenlerle uyumlu bir imzaya sahipse ve bağımsız değişkenden parametreye daraltma dönüştürmesi gerekmiyorsa, örnek yöntem, herhangi bir uzantı yönteminden önce tercih edilir. Bu nedenle, bir noktada bir sınıfa uygun bir örnek yöntemi eklenirse, kullandığınız mevcut bir uzantı üyesi erişilemez hale gelebilir.
Bir uzantı yönteminin yazarı, diğer programcıların özgün uzantıdan öncelikli olabilecek çakışan uzantı yöntemleri yazmasını engelleyemez.
Uzantı yöntemlerini kendi ad alanlarına yerleştirerek sağlamlığı geliştirebilirsiniz. Daha sonra kitaplığınızın tüketicileri bir ad alanı ekleyebilir veya bu ad alanını dışlayabilir ya da kitaplığın geri kalanından ayrı olarak ad alanları arasından seçim yapabilir.
Arabirimleri genişletmek, özellikle de arabirimin veya sınıfın sahibi değilseniz sınıfları genişletmekten daha güvenli olabilir. Arabirimdeki bir değişiklik, bunu uygulayan her sınıfı etkiler. Bu nedenle, yazarın arabirime yöntem ekleme veya değiştirme olasılığı daha düşük olabilir. Ancak, bir sınıf aynı imzaya sahip uzantı yöntemlerine sahip iki arabirim uygularsa, her iki uzantı yöntemi de görünür olmaz.
Kullanabileceğiniz en özel türü genişletin. Türlerin hiyerarşisinde, başka birçok türün türetildiği bir tür seçerseniz, örnek yöntemlerinin veya diğer uzantı yöntemlerinin sizinkine müdahale etme olasılığı vardır.
Uzantı yöntemleri, örnek yöntemleri ve özellikler
Kapsam içi bir örnek metot, çağrı ifadesinin argümanlarıyla uyumlu bir imzaya sahip olduğunda, bu örnek metot herhangi bir uzantı metoduna tercih edilir. Uzantı yöntemi daha iyi bir eşleşme olsa bile örnek yönteminin önceliği vardır. Aşağıdaki örnekte, bir ExampleClass
türünde parametresi olan ExampleMethod
adlı bir örnek yöntemi içeren Integer
yer almaktadır. Uzantı yöntemi ExampleMethod
ExampleClass
'i genişletir ve Long
türünde bir parametreye sahiptir.
Class ExampleClass
' Define an instance method named ExampleMethod.
Public Sub ExampleMethod(ByVal m As Integer)
Console.WriteLine("Instance method")
End Sub
End Class
<Extension()>
Sub ExampleMethod(ByVal ec As ExampleClass,
ByVal n As Long)
Console.WriteLine("Extension method")
End Sub
Aşağıdaki koddaki ilk ExampleMethod
çağrısı genişletme yöntemini çağırır, çünkü arg1
Long
'dir ve yalnızca genişletme yöntemindeki Long
parametresiyle uyumludur.
ExampleMethod
'a yapılan ikinci çağrı, bir Integer
bağımsız değişkeni olan arg2
ile birlikte gelir ve örnek metodunu çağırır.
Sub Main()
Dim example As New ExampleClass
Dim arg1 As Long = 10
Dim arg2 As Integer = 5
' The following statement calls the extension method.
example.exampleMethod(arg1)
' The following statement calls the instance method.
example.exampleMethod(arg2)
End Sub
Şimdi iki yöntemde parametrelerin veri türlerini tersine çevirin:
Class ExampleClass
' Define an instance method named ExampleMethod.
Public Sub ExampleMethod(ByVal m As Long)
Console.WriteLine("Instance method")
End Sub
End Class
<Extension()>
Sub ExampleMethod(ByVal ec As ExampleClass,
ByVal n As Integer)
Console.WriteLine("Extension method")
End Sub
Bu kez içindeki Main
kod her iki kez de örnek yöntemini çağırır. Bunun nedeni, hem arg1
hem de arg2
için Long
'ya genişletme dönüştürmesi olması ve her iki durumda da örnek yönteminin uzantı yönteminden öncelikli olmasıdır.
Sub Main()
Dim example As New ExampleClass
Dim arg1 As Long = 10
Dim arg2 As Integer = 5
' The following statement calls the instance method.
example.ExampleMethod(arg1)
' The following statement calls the instance method.
example.ExampleMethod(arg2)
End Sub
Bu nedenle, bir uzantı yöntemi mevcut bir örnek yönteminin yerini alamaz. Ancak, bir uzantı yöntemi bir örnek yöntemiyle aynı ada sahipse ancak imzalar çakışmadığında, her iki yönteme de erişilebilir. Örneğin, ExampleClass
sınıfı içinde, ExampleMethod
adlı ve bağımsız değişken almayan bir yöntem varsa, aşağıdaki kodda gösterildiği gibi aynı ada sahip ancak farklı imzalara sahip genişletme yöntemlerine izin verilir.
Imports System.Runtime.CompilerServices
Module Module3
Sub Main()
Dim ex As New ExampleClass
' The following statement calls the extension method.
ex.ExampleMethod("Extension method")
' The following statement calls the instance method.
ex.ExampleMethod()
End Sub
Class ExampleClass
' Define an instance method named ExampleMethod.
Public Sub ExampleMethod()
Console.WriteLine("Instance method")
End Sub
End Class
<Extension()>
Sub ExampleMethod(ByVal ec As ExampleClass,
ByVal stringParameter As String)
Console.WriteLine(stringParameter)
End Sub
End Module
Bu kodun çıktısı aşağıdaki gibidir:
Extension method
Instance method
Durum özelliklerle daha basittir: Uzantı yöntemi genişletilen sınıfın özelliğiyle aynı ada sahipse, uzantı yöntemi görünür değildir ve erişilemez.
Uzantı yöntemi önceliği
Aynı imzalara sahip iki uzantı yöntemi kapsam içinde ve erişilebilir olduğunda, daha yüksek önceliğe sahip olan yöntem çağrılır. Uzantı yönteminin önceliği, yöntemi kapsama getirmek için kullanılan mekanizmayı temel alır. Aşağıdaki liste, en yüksekten en düşüğe kadar öncelik hiyerarşisini gösterir.
Geçerli modülün içinde tanımlanan uzantı yöntemleri.
Geçerli ad alanındaki veya herhangi bir üst ad alanındaki veri türlerinin içinde tanımlanan uzantı yöntemleri, alt ad alanlarının üst ad alanlarına göre daha yüksek önceliğe sahiptir.
Geçerli dosyadaki herhangi bir tür içeri aktarma işleminde tanımlanan uzantı yöntemleri.
Geçerli dosyadaki herhangi bir ad alanı içindeki uzantı yöntemleri tanımlanır.
Proje düzeyindeki herhangi bir tür içeri aktarma işleminde tanımlanan uzantı yöntemleri.
Proje düzeyindeki ad alanı içeri aktarma işlemlerinde tanımlanan uzantı yöntemleri.
Öncelik belirsizliği çözmezse, çağırdığınız yöntemi belirtmek için tam adı kullanabilirsiniz. Önceki örnekteki Print
yöntemi, StringExtensions
adlı bir modülde tanımlanmışsa, tam ad StringExtensions.Print(example)
yerine example.Print()
olacaktır.