Sdílet prostřednictvím


Metody rozšíření (Visual Basic)

Rozšiřující metody umožňují vývojářům přidat vlastní funkce k datovým typům, které jsou již definovány, bez vytváření nového odvozeného typu.Rozšiřující metody umožňují napsat metodu, která může být volána, jako by šlo o metodu instance existujícího typu.

Poznámky

Metoda rozšíření může být pouze procedura Sub nebo Function.Nelze definovat vlastnost rozšíření, pole nebo události.Všechny metody rozšíření musí být označeny pomocí atributu rozšíření <Extension()> z oboru názvů System.Runtime.CompilerServices.

První parametr v metodě rozšíření určuje, jaký typ dat metoda rozšiřuje.Při spuštění metody je první parametr vázán na datový typ, který vyvolá metodu instance.

Příklad

Description

Následující příklad definuje rozšíření Print pro datový typ String.Metoda používá Console.WriteLine pro zobrazení řetězce.Parametr metody Print, aString, stanoví, že metody rozšíří třídu String.

Imports System.Runtime.CompilerServices

Module StringExtensions

    <Extension()> 
    Public Sub Print(ByVal aString As String)
        Console.WriteLine(aString)
    End Sub 

End Module

Všimněte si, že definice metody rozšíření je označena atributem rozšíření <Extension()>.Označení modulu, ve kterém je definována metoda, je nepovinné, ale každá rozšiřující metoda musí být označena.System.Runtime.CompilerServices musí být importovány, pokud chcete získat přístup k atributu rozšíření.

Metody rozšíření lze deklarovat jen v modulech.Modul, ve kterém je definována rozšiřující metoda, obvykle není stejný modul jako ten, ve kterém je volán.Namísto toho se importuje modul, který obsahuje metodu rozšíření importu (pokud je nutné, pro přivedení do rozsahu).Jakmile bude modul obsahující Print v oboru, lze volat metodu, jako by šlo o běžnou metodu instance, která nepřijímá žádné argumenty, jako například 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

V dalším příkladu PrintAndPunctuate je také rozšíření String, tentokrát definováno se dvěma parametry.První parametr aString stanoví, že metoda rozšíření rozšiřuje parametr String.Druhý parametr punc je určen jako řetězec interpunkčního znaménka, které je předáno jako argument při volání metody.Metoda zobrazí řetězec následovaný interpunkčními znaménky.

<Extension()> 
Public Sub PrintAndPunctuate(ByVal aString As String, 
                             ByVal punc As String)
    Console.WriteLine(aString & punc)
End Sub

Je volána metoda odesláním v argumentu řetězce pro punc: example.PrintAndPunctuate(".")

Následující příklad ukazuje definované a volané výrazy Print a PrintAndPunctuate.System.Runtime.CompilerServices importován v modulu definice s cílem umožnit přístup k atributu rozšíření.

Kód

Imports System.Runtime.CompilerServices

Module StringExtensions

    <Extension()> 
    Public Sub Print(ByVal aString As String)
        Console.WriteLine(aString)
    End Sub

    <Extension()> 
    Public Sub PrintAndPunctuate(ByVal aString As String, 
                                 ByVal punc As String)
        Console.WriteLine(aString & punc)
    End Sub

End Module

Dále se rozšiřující metody uvedou do rozsahu a budou volány.

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

Komentáře

Ke spouštění těchto nebo podobných metod rozšíření stačí, aby byly v oboru.Pokud je modul, který obsahuje rozšiřující metodu v oboru, je zobrazen v technologii IntelliSense a může být volán, jako by šlo o běžnou metodu instance.

Všimněte si, že když jsou metody vyvolány, žádný argument se pro první parametr neodešle.Parametr aString v předchozí definici metody je vázán na example, instanci String, která je volá.Kompilátor použije example jako argument odeslaný na první parametr.

Pokud se volá metoda rozšíření pro objekt, který je nastaven na Nothing, metoda rozšíření se zavolá.To se nevztahuje na běžné metody instancí.Můžete explicitně zjišťovat Nothing v rozšířené metodě.

Typy, které lze rozšířit

Můžete definovat rozšiřující metodu pro většinu typů, které mohou být zastoupeny v seznamu parametrů jazyka Visual Basic, včetně následujících:

  • Třídy (typy odkazů)

  • Struktury (typy hodnot)

  • Rozhraní

  • Delegáti

  • Argumenty ByRef a ByVal

  • Obecné parametry metody

  • Pole

Vzhledem k tomu, že první parametr určuje datový typ, který rozšiřující metoda rozšiřuje, je vyžadován a nemůže být nepovinný.Z tohoto důvodu Optional parametry a ParamArray parametry nemohou být první parametr v seznamu parametrů.

Rozšiřující metody nejsou brány v úvahu v pozdní vazbě.V následujícím příkladu vyvolává výraz anObject.PrintMe() stejnou výjimku MissingMemberException, kterou byste viděli, kdybyste odstranili druhou definici metody rozšíření PrintMe.

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

Doporučené postupy

Rozšiřující metody poskytují pohodlný a účinný způsob, jak rozšířit existující typ.Chcete-li je však úspěšně používat, existují některé body, které je třeba zvážit.Tyto úvahy platí hlavně pro autory knihoven tříd, ale mohou ovlivnit jakékoli aplikace, které používají rozšiřující metody.

Obecně jsou zranitelnější metody rozšíření přidané do typů, které nevlastníte, než metody rozšíření přidané do typů, které řídíte.Ve třídách, které nevlastníte, může dojít k řadě událostí, které mohou narušit vaše metody rozšíření.

  • Pokud existuje kterýkoli přístupný instanční člen, která má podpis, který je kompatibilní s argumenty v příkazu volání, bez zužujících převodů požadovaných argumentem pro parametr, bude použita instanční metoda před jakoukoli metodou rozšíření.Proto pokud metoda příslušné instance je přidána do třídy v určitém okamžiku, existující člen rozšíření, na kterého spoléháte, může být nepřístupný.

  • Autor metody rozšíření nemůže ostatním programátorům zabránit ve vytváření konfliktních metod rozšíření, které mohou mít přednost před původním rozšířením.

  • Můžete zlepšit odolnost vložením rozšiřujících metod ve vlastním oboru názvů.Spotřebitelé knihovny pak mohou zahrnout nebo vyloučit obor názvů, nebo volit mezi obory názvů odděleně od zbytku knihovny.

  • Více než rozšířit třídy může být bezpečnější rozšířit rozhraní, zejména v případě, že rozhraní nebo třídu nevlastníte.Změna v rozhraní se týká každé třídy, která jej implementuje.Je tedy nepravděpodobné, že autor bude chtít přidat nebo změnit metody v rozhraní.Pokud třída implementuje dvě rozhraní, která mají stejnou signaturu metody rozšíření, žádná rozšiřující metoda není nicméně viditelná.

  • Rozšiřte co nejspecifičtější typ.Pokud v hierarchii typů vyberete typ, z něhož je odvozeno mnoho jiných typů, existují vrstvy možností pro zavedení metody instance nebo jiných rozšiřujících metod, které by mohou narušovat vaše metody.

Rozšiřující metody, metody instance a vlastnosti

Pokud má metoda instance instance v oboru podpis, který je kompatibilní s argumenty volání příkazu, metoda instance bude zvolena v preferenci pro libovolné metody rozšíření.Instanční metoda má přednost, i když rozšiřující metoda představuje lepší shodu.V následujícím příkladu obsahuje výraz ExampleClass metodu instance pojmenovanou ExampleMethod, která má jeden parametr typu Integer.Rozšiřující metoda ExampleMethod rozšiřuje ExampleClass a má jeden parametr typu Long.

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

První volání funkce ExampleMethod v následujícím kódu volá metodu rozšíření, protože arg1 je Long a je kompatibilní pouze s parametrem Long v metodě rozšíření.Druhé volání pro ExampleMethod má argument Integer, arg2, a volá metodu instance.

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

Nyní obraťte datové typy parametrů ve dvou metodách:

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

Tentokrát kód v Main volá metodu instance obou časů.Důvodem je, že arg1 i arg2 mají rozšiřující převod na Long a metoda instance přechází v obou případech rozšiřující metodě.

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

Proto rozšiřující metoda nemůže nahradit stávající metodu instance.Pokud však rozšiřující metoda má stejný název jako metoda instance, ale podpisy nejsou v rozporu, obě metody jsou přístupné.Například pokud třída ExampleClass obsahuje metodu s názvem ExampleMethod která nebere žádné argumenty, rozšiřující metody se stejným názvem, ale různými podpisy, jsou povoleny, jak je znázorněno v následujícím kódu.

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

Výstup tohoto kódu je následující:

Extension method

Instance method

Situace je jednodušší s vlastnostmi: pokud rozšiřující metoda má stejný název jako vlastnost třídy, kterou rozšiřuje, rozšiřující metoda není viditelná a není přístupná.

Priorita rozšiřující metody

Když dvě rozšiřující metody, které mají stejné podpisy, jsou v oboru a jsou přístupné, bude vyvolána ta, která má vyšší prioritu.Přednost metody rozšíření je založena na mechanismu použitém k uvedení metody do oboru.Následující seznam obsahuje hierarchii priority od nejvyšší po nejnižší.

  1. Rozšiřující metody definované uvnitř aktuálního modulu.

  2. Rozšiřující metody definované uvnitř datových typů v aktuálním oboru názvů, nebo v jednom z jeho rodičů s podřízenými obory názvů, které mají vyšší prioritu než nadřazené obory názvů.

  3. Rozšiřující metody definované uvnitř libovolných importů typu v aktuálním souboru.

  4. Rozšiřující metody definované uvnitř libovolných importů oboru názvu v aktuálním souboru.

  5. Rozšiřující metody definované uvnitř libovolných importů na úrovni projektu.

  6. Rozšiřující metody definované uvnitř libovolných importů oboru názvu na úrovni projektu.

Pokud přednost nevyřeší nejednoznačnosti, můžete určit metodu, kterou voláte, přes plně kvalifikovaný název.Pokud Print metoda v předchozím příkladu je definována v modulu s názvem StringExtensions, je plně kvalifikovaný název StringExtensions.Print(example) místo example.Print().

Viz také

Referenční dokumentace

System.Runtime.CompilerServices

Metody rozšíření (Průvodce programováním v C#)

Module – příkaz

Atributy (C# and Visual Basic)

ExtensionAttribute

Koncepty

Parametry a argumenty procedury (Visual Basic)

Volitelné parametry (Visual Basic)

Pole parametrů (Visual Basic)

Rozsah v jazyce Visual Basic