Share via


Uzantı Yöntemleri (Visual Basic)

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, Subveya Functionöğesine uygulanabilir. Bunu veya öğesine ClassStructureuygularsanız, Visual Basic derleyicisi hata BC36550 oluşturur, "'Extension' özniteliği yalnızca 'Module', 'Sub' veya 'function' bildirimlerine uygulanabilir".

Örnek

Aşağıdaki örnek, veri türü için String bir Print uzantı tanımlar. yöntemi bir dizeyi görüntülemek için kullanır Console.WriteLine . yönteminin Print parametresi, aStringyönteminin sınıfını String genişletir.

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, gerekirse kapsamına almak için içeri aktarılır. içeren Print modül kapsam dahilinde olduktan sonra, yöntemi gibi 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, PrintAndPunctuatebu kez iki parametreyle tanımlanan bir uzantısıdır String. İlk parametresi, aStringuzantı yönteminin genişletildiğini Stringbelirtir. İ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

yöntemi, için puncbir dize bağımsız değişkeni göndererek çağrılır: example.PrintAndPunctuate(".")

Aşağıdaki örnekte, tanımlanan ve PrintAndPunctuate çağrılan örnekler gösterilmektedirPrint. 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 parametreaString, onları çağıran örneğine exampleString bağlıdır. Derleyici, ilk parametreye gönderilen bağımsız değişken olarak kullanır example .

olarak ayarlanmış Nothingbir 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 açıkça denetleyebilirsiniz Nothing .

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 (başvuru türleri)
  • Yapılar (değer türleri)
  • Arabirimler
  • 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. Aşağıdaki örnekte deyimianObject.PrintMe(), ikinci PrintMe uzantı yöntemi tanımının silinip silinmediğini göreceğiniz özel durum olan bir MissingMemberException özel durum oluşturur.

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.

  • Bağımsız değişkenden parametreye daraltma dönüştürmesi gerekmeyen, çağırma deyimindeki bağımsız değişkenlerle uyumlu bir imzaya sahip erişilebilir bir örnek üyesi varsa, örnek yöntemi herhangi bir uzantı yöntemi tercihinde kullanılır. 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 örnek yönteminin çağıran deyiminin bağımsız değişkenleriyle uyumlu bir imzası olduğunda, örnek yöntemi herhangi bir uzantı yöntemine tercih edilir. Uzantı yöntemi daha iyi bir eşleşme olsa bile örnek yönteminin önceliği vardır. Aşağıdaki örnekte, ExampleClass türünde Integerbir parametresi olan adlı ExampleMethod bir örnek yöntemi içerir. Uzantı yöntemi ExampleMethod genişletir ExampleClassve türünde Longbir 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 çağrısı ExampleMethod uzantı yöntemini çağırır, çünkü arg1Long ve yalnızca uzantı yöntemindeki Long parametresiyle uyumludur. İkinci çağrısı ExampleMethod bir Integer bağımsız değişkenine arg2sahiptir ve örnek yöntemini ç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 hem arg2 de arg1 için genişletme dönüştürmesi Longolması ve örnek yönteminin her iki durumda da 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, sınıfı ExampleClass bağımsız değişken içermeyen adlı ExampleMethod bir yöntem içeriyorsa, aşağıdaki kodda gösterildiği gibi aynı ada ancak farklı imzalara sahip uzantı 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.

  1. Geçerli modülün içinde tanımlanan uzantı yöntemleri.

  2. Alt ad alanlarının üst ad alanlarına göre daha yüksek önceliğe sahip olduğu, geçerli ad alanında veya üst ad alanında bulunan veri türlerinin içinde tanımlanan uzantı yöntemleri.

  3. Geçerli dosyadaki herhangi bir tür içeri aktarma işleminde tanımlanan uzantı yöntemleri.

  4. Geçerli dosyadaki herhangi bir ad alanının içinde tanımlanan uzantı yöntemleri içeri aktarılır.

  5. Proje düzeyindeki herhangi bir tür içeri aktarma işleminde tanımlanan uzantı yöntemleri.

  6. 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öntem adlı StringExtensionsbir modülde tanımlanmışsa, tam ad yerine example.Print()olurStringExtensions.Print(example).

Ayrıca bkz.