Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
A bővítménymódszerekkel a fejlesztők új származtatott típus létrehozása nélkül adhatnak hozzá egyéni funkciókat a már definiált adattípusokhoz. A bővítménymetódusok lehetővé teszik olyan metódus írását, amely úgy hívható meg, mintha a meglévő típusú példánymetódus lenne.
Megjegyzések
Kiterjesztési metódus csak eljárás Sub
vagy Function
lehet. Bővítménytulajdonságot, mezőt vagy eseményt nem definiálhat. Minden kiterjesztési metódust a névtér bővítményattribútumával <Extension>
System.Runtime.CompilerServices kell megjelölni, és egy modulban kell definiálni. Ha egy bővítménymetódus egy modulon kívül van definiálva, a Visual Basic fordító hibaüzenetet hoz létre BC36551: "A bővítménymetódusok csak modulokban határozhatók meg".
A bővítménymetódus definíciójának első paramétere határozza meg, hogy a metódus melyik adattípust bővíti ki. A metódus futtatásakor az első paraméter a metódust meghívó adattípus példányához lesz kötve.
Az Extension
attribútum csak Visual Basic Module
, Sub
vagy Function
esetén alkalmazható. Ha egy Class
vagy Structure
-re alkalmazza, a Visual Basic fordító hibát ad BC36550, "a 'Extension' attribútum csak a 'Module', 'Sub' vagy 'Function' deklarációkra alkalmazható".
példa
Az alábbi példa az Print
adattípus bővítményét String határozza meg. A metódus egy sztring megjelenítésére használja Console.WriteLine
. A metódus paramétere Print
megállapítja, aString
hogy a metódus kiterjeszti az osztályt String .
Imports System.Runtime.CompilerServices
Module StringExtensions
<Extension()>
Public Sub Print(ByVal aString As String)
Console.WriteLine(aString)
End Sub
End Module
Figyelje meg, hogy a bővítménymetódus definíciója a bővítményattribútummal <Extension()>
van megjelölve. A modul megjelölése, amelyben a metódus definiálva van, nem kötelező, de minden bővítménymetódust meg kell jelölni.
System.Runtime.CompilerServices a bővítményattribútum eléréséhez importálni kell.
A bővítménymetelyek csak modulokon belül deklarálhatók. Általában az a modul, amelyben egy bővítménymetódus definiálva van, nem ugyanaz a modul, mint amelyikben meghívják. Ehelyett a bővítménymetódust tartalmazó modult importálja a rendszer, ha szükséges, hogy hatókörbe helyezze. Miután a modul Print
hatókörbe került, a metódus úgy hívható meg, mintha egy szokásos példánymetódus lenne, amely nem vesz fel argumentumokat, például ToUpper
:
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
A következő példa, PrintAndPunctuate
, szintén egy bővítmény String, ezúttal két paraméterrel definiálva. Az első paraméter megállapítja, aString
hogy a bővítménymetódus kiterjeszthető String. A második paraméter, punc
, egy írásjelekből álló sztringnek van szánva, amelyet argumentumként ad át, amikor a metódust meghívják. A metódus megjeleníti a sztringet, majd az írásjeleket.
<Extension()>
Public Sub PrintAndPunctuate(ByVal aString As String,
ByVal punc As String)
Console.WriteLine(aString & punc)
End Sub
A metódus meghívásához sztringargumentumot kell küldeni a következőhöz punc
: example.PrintAndPunctuate(".")
Az alábbi példa bemutatja Print
és PrintAndPunctuate
definiálja és meghívja.
System.Runtime.CompilerServices a definíciómodulba importálja a bővítményattribútumhoz való hozzáférés engedélyezéséhez.
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
Ezután a bővítménymetelyek hatókörbe kerülnek, és a következőt hívják:
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
Mindössze annyit kell tenni ahhoz, hogy képes legyen futtatni ezeket vagy hasonló bővítménymódszereket, hogy hatókörben legyenek. Ha a bővítménymetódust tartalmazó modul hatókörben van, akkor az látható az IntelliSense-ben, és úgy hívható meg, mintha egy szokásos példánymetódus lenne.
Figyelje meg, hogy a metódusok meghívásakor a rendszer nem küld argumentumot az első paraméterhez. Az aString
előző metódusdefiníciók paramétere az őket meghívó example
példányhoz String
van kötve. A fordító az első paraméternek küldött argumentumként fog használni example
.
Ha a bővítménymetódus egy olyan objektumhoz van meghívva, amely a következőre Nothing
van állítva, a bővítménymetódus végrehajtja a parancsot. Ez nem vonatkozik a szokásos példány metódusokra. A kiterjesztés metódusban kifejezetten ellenőrizheti a Nothing
.
Bővíthető típusok
A Visual Basic paraméterlistában megjeleníthető legtöbb típushoz definiálhat bővítménymetódusokat, beleértve a következőket:
- Osztályok (referenciatípusok)
- Struktúrák (értéktípusok)
- Felületek
- Delegáltak
- ByRef és ByVal argumentumok
- Általános metódusparaméterek
- Tömbök
Mivel az első paraméter a bővítménymetódus által kiterjesztett adattípust adja meg, kötelező megadni, és nem választható. Emiatt Optional
a paraméterek és ParamArray
paraméterek nem lehetnek az első paraméter a paraméterlistában.
A kiterjesztési metódusokat nem vesszük figyelembe a késői kötés során. A következő példában az utasítás anObject.PrintMe()
kivételt MissingMemberException hoz létre, ugyanaz a kivétel, amely akkor jelenik meg, ha a második PrintMe
bővítménymetódus definícióját törölték.
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
Ajánlott eljárások
A bővítménymetelyek kényelmes és hatékony módot biztosítanak egy meglévő típus kiterjesztésére. A sikeres használatukhoz azonban érdemes megfontolni néhány szempontot. Ezek a szempontok elsősorban az osztálykódtárak szerzőire vonatkoznak, de hatással lehetnek a bővítménymetelyeket használó alkalmazásokra.
Általában a nem saját típusokhoz hozzáadott bővítménymetelyek sebezhetőbbek, mint az Ön által vezérelt típusokhoz hozzáadott bővítménymetelyek. Nem saját tulajdonú osztályokban több olyan dolog is előfordulhat, amely zavarhatja a kiterjesztési metódusokat.
Ha létezik olyan akadálymentes példánytag, amely rendelkezik olyan aláírással, amely kompatibilis a hívó utasítás argumentumaival, és nincs szükség az argumentumról paraméterre történő konvertálás szűkítésére, a rendszer a példánymetódust használja a bővítménymetódusok előnyben részesítésére. Ezért ha egy adott időpontban egy megfelelő példánymetódus van hozzáadva egy osztályhoz, előfordulhat, hogy egy meglévő bővítménytag, amelyre támaszkodik, elérhetetlenné válhat.
A bővítménymetódus szerzője nem akadályozhatja meg, hogy más programozók ütköző bővítménymetódusokat írjanak, amelyek elsőbbséget élvezhetnek az eredeti kiterjesztéssel szemben.
A robusztusságot úgy javíthatja, hogy a bővítménymódszereket a saját névterükbe helyezi. A kódtár felhasználói ezután hozzáadhatnak egy névteret, vagy kizárhatják azt, vagy választhatnak a névterek között, a tár többi részétől elkülönítve.
Biztonságosabb lehet az interfészek kiterjesztése, mint az osztályok kiterjesztése, különösen akkor, ha nem rendelkezik a felülettel vagy az osztályokkal. A felület módosítása minden olyan osztályt érint, amely implementálja azt. Ezért előfordulhat, hogy a szerző kevésbé valószínű, hogy metódusokat ad hozzá vagy módosít egy felületen. Ha azonban egy osztály két olyan felületet implementál, amelyek azonos aláírású bővítménymetódusokkal rendelkeznek, egyik bővítménymetódus sem látható.
Terjeszd ki a legspecifikusabb típust. A típusok hierarchiájában, ha olyan típust választ ki, amelyből sok más típus származik, a példánymetodalmok vagy más bővítménymetelyek bevezetésének több lehetősége is van, amelyek zavarhatják az Önét.
Kiterjesztési metódusok, példány metódusok és tulajdonságok
Ha egy hatókörön belüli példány olyan aláírással rendelkezik, amely kompatibilis a hívási utasítás argumentumaival, a rendszer a példánymetódust választja a bővítménymetódusok előnyben részesítése érdekében. A példánymetódus akkor is elsőbbséget élvez, ha a kiterjesztési metódus jobb illeszkedés. Az alábbi példában ExampleClass
egy ExampleMethod
nevű példánymetódust tartalmaz, amelynek egy paramétere van Integer
típusú. A bővítménymetódus ExampleMethod
kiterjeszthető ExampleClass
, és egy típusparamétert Long
is használ.
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 következő kódban az első ExampleMethod
hívás a bővítménymetódust hívja meg, mert arg1
Long
, és csak a bővítménymetódus Long
paraméterével kompatibilis. A második hívásnak ExampleMethod
argumentuma Integer
van, arg2
és meghívja a példány metódusát.
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
Most fordítsa vissza a paraméterek adattípusait a két módszerben:
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
Ezúttal a kód Main
mindkét alkalommal meghívja a példánymetódust. Ennek az az oka, hogy mind arg1
, mind arg2
képes bővülő konverziót végrehajtani Long
-re, és mindkét esetben a példánymetódus elsőbbséget élvez a bővítési metódussal szemben.
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
Ezért a bővítménymetódus nem helyettesítheti a meglévő példánymetódusokat. Ha azonban egy bővítménymetódus neve megegyezik egy példánymetódus nevével, de az aláírások nem ütköznek, mindkét metódus elérhető. Ha például az osztály ExampleClass
olyan metódust ExampleMethod
tartalmaz, amely nem tartalmaz argumentumokat, akkor az azonos nevű, de eltérő aláírású bővítménymetódusok engedélyezettek, ahogyan az alábbi kódban is látható.
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
A kód kimenete a következő:
Extension method
Instance method
A tulajdonságok esetében egyszerűbb a helyzet: ha egy bővítménymetódus neve megegyezik a kiterjesztett osztály tulajdonságával, a bővítménymetódus nem látható, és nem érhető el.
A bővítménymetódus elsőbbsége
Ha két azonos aláírással rendelkező bővítménymetely van hatókörben és elérhető, a rendszer meghívja a magasabb elsőbbséget élvező metódust. A bővítménymetódus elsőbbsége a metódus hatókörbe helyezéséhez használt mechanizmuson alapul. Az alábbi listában a rangsor hierarchiája látható a legmagasabbtól a legalacsonyabbig.
Az aktuális modulban definiált bővítménymetelyek.
Az aktuális névtér adattípusaiban vagy bármelyik szülőnévtérben definiált bővítménymódszerek, ahol a gyermeknévterek magasabb prioritást élveznek, mint a szülőnévterek.
Az aktuális fájl bármely típusimportálásán belül definiált bővítménymetelyek.
Az aktuális fájl bármely névtérimportálásán belül definiált bővítménymetelyek.
A projektszintű importálásokon belül definiált bővítménymetelyek.
A projektszintű névtérimportálásokon belül definiált bővítménymetelyek.
Ha az elsőbbség nem oldja meg a kétértelműséget, a teljesen kvalifikált név megadásával specifikálhatja a hívott metódust. Ha a Print
metódus a korábbi példában egy StringExtensions
nevű modulban van definiálva, akkor a teljes név StringExtensions.Print(example)
, nem pedig example.Print()
.