Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
V praxi jsou pravidla pro určení rozlišení přetížení určena k nalezení přetížení, které je "nejblíže" k zadaným skutečným argumentům. Pokud existuje metoda, jejíž typy parametrů odpovídají typům argumentů, je tato metoda zřejmě nejblíže. Pokud jsou všechny jeho typy parametrů užší než (nebo stejné jako) typy parametrů druhé metody, je tato metoda blíže než jiná. Pokud parametry žádné metody nejsou užší než ostatní, neexistuje způsob, jak určit, která metoda je blíže argumentům.
Poznámka. Řešení přetížení nebere v úvahu očekávaný návratový typ metody.
Všimněte si také, že vzhledem k pojmenované syntaxi parametru nemusí být řazení skutečných a formálních parametrů stejné.
Vzhledem ke skupině metod se nejužitečnější metoda ve skupině pro seznam argumentů určuje pomocí následujícího postupu. Pokud po použití konkrétního kroku nezůstanou v sadě žádní členové, dojde k chybě v době kompilace. Pokud v sadě zůstane jenom jeden člen, je tento člen nejužitevějším členem. Postupujte takto:
Za prvé, pokud nebyly zadány žádné argumenty typu, použijte odvození typu u všech metod, které mají parametry typu. Pokud je odvození typu pro metodu úspěšné, použijí se pro danou konkrétní metodu argumenty odvozeného typu. Pokud odvození typu pro metodu selže, pak je tato metoda vyloučena ze sady.
V dalším kroku vyloučíte všechny členy ze sady, které jsou nepřístupné nebo nelze použít (seznam použitelnosti argumentů oddílu) v seznamu argumentů.
Pokud jsou
AddressOfjeden nebo více argumentů výrazy nebo výrazy lambda, vypočítejte úrovně uvolnění delegáta pro každý argument, jak je uvedeno níže. Pokud nejhorší (nejnižší) úroveň uvolnění delegáta jeNhorší než nejnižší úroveň uvolnění delegáta vM, pak eliminujteNze sady. Úrovně uvolnění delegáta jsou následující:Úroveň uvolnění delegáta chyby – pokud
AddressOfnení možné převést na typ delegáta nebo lambda.Zúžení delegovaného uvolnění návratového typu nebo parametrů – pokud je
AddressOfargument nebo lambda s deklarovaným typem a převod z návratového typu delegáta na návratový typ delegáta se zužuje; nebo pokud je argument regulární lambda a převod z některého z jeho návratových výrazů na návratový typ delegáta se zúží, nebo je-li argument asynchronní lambda a návratový typ delegáta jeTask(Of T)a převod z některého z jeho návratových výrazů naTzúžení; nebo pokud je argument lambda iterátoru a delegující návratový typIEnumerator(Of T)neboIEnumerable(Of T)a převod z některého z jeho výnosných operandů naTzúžení.Rozšíření uvolnění delegáta na delegáta bez podpisu - pokud je typ delegáta
System.DelegateneboSystem.ObjectSystem.MultiCastDelegatenebo .Uvolnění návratu nebo argumentů delegování delegáta – pokud je
AddressOfargument nebo lambda s deklarovaným návratovým typem a typu delegáta chybí návratový typ, nebo pokud je argument lambda s jedním nebo více návratovými výrazy a typ delegáta nemá návratový typ; nebo pokud jeAddressOfargument nebo lambda bez parametrů a typ delegáta má parametry.Rozšíření delegovaného uvolnění návratového typu - pokud je
AddressOfargument nebo lambda s deklarovaným návratovým typem, a existuje rozšiřující převod z jeho návratového typu na delegáta; nebo je-li argument regulární lambda, kde převod ze všech návratových výrazů na návratový typ delegáta rozšiřuje nebo identita s alespoň jedním rozšířením; nebo pokud je argument asynchronní lambda a delegát jeTask(Of T)neboTaska převod ze všech vrácených výrazů naTObject/v uvedeném pořadí je rozšiřující nebo identita s alespoň jedním rozšířením; nebo pokud je argumentem lambda iterátor a delegát jeIEnumerator(Of T)neboIEnumerable(Of T)IEnumeratorneboIEnumerablea převod ze všech vrácených výrazů naT/Objectrozšíření nebo identitu s alespoň jedním rozšířením.Uvolnění delegáta identity – pokud je argument nebo
AddressOflambda, který přesně odpovídá delegátovi, bez rozšíření nebo zužování nebo vyřazení parametrů nebo vrácení nebo výnosu. Pokud některé členy sady nevyžadují zužující převody, aby byly použitelné pro některý z argumentů, odstraňte všechny členy, které dělají. Například:
Sub f(x As Object) End Sub Sub f(x As Short) End Sub Sub f(x As Short()) End Sub f("5") ' picks the Object overload, since String->Short is narrowing f(5) ' picks the Object overload, since Integer->Short is narrowing f({5}) ' picks the Object overload, since Integer->Short is narrowing f({}) ' a tie-breaker rule subsequent to [3] picks the Short() overloadDále se odstranění provádí na základě zužování následujícím způsobem. (Všimněte si, že pokud je možnost Strict zapnutá, pak všichni členové, kteří vyžadují zúžení, již byli vyhodnoceni jako neaplikovatelné (oddíl Použitelnost seznamu argumentů) a odebráni krokem 2.)
- Pokud některé členy instance sady vyžadují pouze zúžení převodů, kde je
Objecttyp výrazu argumentu , odstraňte všechny ostatní členy. - Pokud sada obsahuje více než jeden člen, který vyžaduje zúžení pouze od
Object, pak je vyvolání cílového výrazu přetříděn jako přístup metody s pozdní vazbou (a pokud typ obsahující skupinu metod je rozhraní, nebo pokud některý z příslušných členů byl členy rozšíření). - Pokud existují kandidáti, kteří vyžadují pouze zužování číselných literálů, zvolte nejpřesnější ze všech zbývajících kandidátů pomocí následujícího postupu. Pokud vítěz vyžaduje pouze zúžení z číselných literálů, je vybrán jako výsledek rozlišení přetížení; jinak se jedná o chybu.
Poznámka. Odůvodněním tohoto pravidla je, že pokud je program volně typovaný (tj. většina nebo všechny proměnné jsou deklarovány jako
Object), rozlišení přetížení může být obtížné, pokud je mnoho převodů zužujícíObject. Místo toho, aby řešení přetížení selhalo v mnoha situacích (vyžaduje silné psaní argumentů volání metody), rozlišení příslušné přetížené metody volání je odloženo do doby běhu. To umožňuje, aby volání volně zadaného typu bylo úspěšné bez dalších přetypování. Nešťastným vedlejším účinkem je však to, že provedení pozdního volání vyžaduje přetypování cíle volání naObject. V případě hodnoty struktury to znamená, že hodnota musí být vložena do dočasného rámečku. Pokud se metoda nakonec zavolá pokusí změnit pole struktury, tato změna bude ztracena, jakmile metoda vrátí. Rozhraní jsou z tohoto speciálního pravidla vyloučena, protože pozdní vazby se vždy překládají proti členům třídy modulu runtime nebo typu struktury, které mohou mít jiné názvy než členové rozhraní, která implementují.- Pokud některé členy instance sady vyžadují pouze zúžení převodů, kde je
Pokud některé metody instance zůstanou v sadě, které nevyžadují zúžení, odstraňte všechny rozšiřující metody ze sady. Například:
Imports System.Runtime.CompilerServices Class C3 Sub M1(d As Integer) End Sub End Class Module C3Extensions <Extension> _ Sub M1(c3 As C3, c As Long) End Sub <Extension> _ Sub M1(c3 As C3, c As Short) End Sub End Module Module Test Sub Main() Dim c As New C3() Dim sVal As Short = 10 Dim lVal As Long = 20 ' Calls C3.M1, since C3.M1 is applicable. c.M1(sVal) ' Calls C3Extensions.M1 since C3.M1 requires a narrowing conversion c.M1(lVal) End Sub End ModulePoznámka. Metody rozšíření se ignorují, pokud existují vhodné metody instance, které zaručují, že přidání importu (které by mohly přinést nové rozšiřující metody do oboru) nezpůsobí volání existující metody instance, aby se znovu svážela s rozšiřující metodou. Vzhledem k širokému rozsahu některých rozšiřujících metod (tj. metod definovaných na rozhraních a/nebo parametrech typu) je to bezpečnější přístup k vazbám na rozšiřující metody.
V dalším kroku, pokud je při zadání libovolných dvou členů množiny
MaNjeMkonkrétnější ( specifika oddílů členů/typů zadaných seznamem argumentů), nežNje uveden seznam argumentů, odstraňteNze sady. Pokud v sadě zůstává více než jeden člen a zbývající členy nejsou stejně specifické vzhledem k seznamu argumentů, výsledkem chyby v době kompilace.Jinak platí, že pokud jsou nastaveny jakékoli dva členy sady,
MaNv uvedeném pořadí použijte následující pravidla pro svázání:Pokud
Mnemá parametr ParamArray, aleNdělá, nebo pokud obojí dělá, aleMpředává méně argumentů do parametru ParamArray, nežNdělá, odstraňteNze sady. Například:Module Test Sub F(a As Object, ParamArray b As Object()) Console.WriteLine("F(Object, Object())") End Sub Sub F(a As Object, b As Object, ParamArray c As Object()) Console.WriteLine("F(Object, Object, Object())") End Sub Sub G(Optional a As Object = Nothing) Console.WriteLine("G(Object)") End Sub Sub G(ParamArray a As Object()) Console.WriteLine("G(Object())") End Sub Sub Main() F(1) F(1, 2) F(1, 2, 3) G() End Sub End ModuleVýše uvedený příklad vytvoří následující výstup:
F(Object, Object()) F(Object, Object, Object()) F(Object, Object, Object()) G(Object)Poznámka. Když třída deklaruje metodu s parametrem paramarray, není neobvyklé zahrnout některé rozšířené formuláře jako běžné metody. Tímto způsobem je možné zabránit přidělení instance pole, ke kterému dochází při vyvolání rozšířené formy metody s parametrem paramarray.
Pokud
Mje definován ve více odvozených typech nežN, odstraňteNze sady. Například:Class Base Sub F(Of T, U)(x As T, y As U) End Sub End Class Class Derived Inherits Base Overloads Sub F(Of T, U)(x As U, y As T) End Sub End Class Module Test Sub Main() Dim d As New Derived() ' Calls Derived.F d.F(10, 10) End Sub End ModuleToto pravidlo platí také pro typy, na které jsou definovány metody rozšíření. Například:
Imports System.Runtime.CompilerServices Class Base End Class Class Derived Inherits Base End Class Module BaseExt <Extension> _ Sub M(b As Base, x As Integer) End Sub End Module Module DerivedExt <Extension> _ Sub M(d As Derived, x As Integer) End Sub End Module Module Test Sub Main() Dim b As New Base() Dim d As New Derived() ' Calls BaseExt.M b.M(10) ' Calls DerivedExt.M d.M(10) End Sub End ModulePokud
MaNjsou rozšiřující metody a cílový typMje třída nebo struktura a cílový typNje rozhraní, odstraňteNze sady. Například:Imports System.Runtime.CompilerServices Interface I1 End Interface Class C1 Implements I1 End Class Module Ext1 <Extension> _ Sub M(i As I1, x As Integer) End Sub End Module Module Ext2 <Extension> _ Sub M(c As C1, y As Integer) End Sub End Module Module Test Sub Main() Dim c As New C1() ' Calls Ext2.M, because Ext1.M is hidden since it extends ' an interface. c.M(10) ' Calls Ext1.M CType(c, I1).M(10) End Sub End ModulePokud
MaNjsou rozšiřující metody a cílový typMaNjsou identické po nahrazení parametru typu a cílový typ před nahrazením parametruMtypu neobsahuje parametry typu, ale cílový typNdělá, pak má méně parametrů typu než cílový typN, eliminovatNze sady. Například:Imports System.Runtime.CompilerServices Module Module1 Sub Main() Dim x As Integer = 1 x.f(1) ' Calls first "f" extension method Dim y As New Dictionary(Of Integer, Integer) y.g(1) ' Ambiguity error End Sub <Extension()> Sub f(x As Integer, z As Integer) End Sub <Extension()> Sub f(Of T)(x As T, z As T) End Sub <Extension()> Sub g(Of T)(y As Dictionary(Of T, Integer), z As T) End Sub <Extension()> Sub g(Of T)(y As Dictionary(Of T, T), z As T) End Sub End ModulePřed nahrazením argumentů typu, pokud
Mje méně obecný ( generická část) nežN, odstraňteNze sady.Pokud
Mnení metoda rozšíření aNje, odstraňteNze sady.Pokud
MaNjsou rozšiřující metody aMbyly nalezeny předN(Section Extension Method Collection), odstraňteNze sady. Například:Imports System.Runtime.CompilerServices Class C1 End Class Namespace N1 Module N1C1Extensions <Extension> _ Sub M1(c As C1, x As Integer) End Sub End Module End Namespace Namespace N1.N2 Module N2C1Extensions <Extension> _ Sub M1(c As C1, y As Integer) End Sub End Module End Namespace Namespace N1.N2.N3 Module Test Sub Main() Dim x As New C1() ' Calls N2C1Extensions.M1 x.M1(10) End Sub End Module End NamespacePokud byly metody rozšíření nalezeny ve stejném kroku, jsou tyto metody rozšíření nejednoznačné. Volání může být vždy nejednoznačné pomocí názvu standardního modulu obsahujícího rozšiřující metodu a volání metody rozšíření, jako by to byl běžný člen. Například:
Imports System.Runtime.CompilerServices Class C1 End Class Module C1ExtA <Extension> _ Sub M(c As C1) End Sub End Module Module C1ExtB <Extension> _ Sub M(c As C1) End Sub End Module Module Main Sub Test() Dim c As New C1() C1.M() ' Ambiguous between C1ExtA.M and BExtB.M C1ExtA.M(c) ' Calls C1ExtA.M C1ExtB.M(c) ' Calls C1ExtB.M End Sub End ModulePokud
MiNoba požadované typy odvozují argumenty typu aMnevyžadují určení dominantního typu pro některý z argumentů typu (tj. každý argument typu odvozený na jeden typ), aleNvyloučil zeNsady.Poznámka. Toto pravidlo zajišťuje, že řešení přetížení, které bylo úspěšné v předchozích verzích (kde odvození více typů argumentu typu způsobí chybu), bude pokračovat ve stejných výsledcích.
Pokud se provádí řešení přetížení k vyřešení cíle výrazu pro vytvoření delegáta z
AddressOfvýrazu, a delegát aMjsou funkce, zatímcoNje podprogram, odstraňteNze sady. Podobně platí, že pokud delegát aMjsou podprogramy, zatímcoNje funkce, eliminujteNze sady.Pokud
Mjste místo explicitních argumentů nepoužili žádné volitelné výchozí hodnoty parametrů, aleNvyloučiliNjste je ze sady.Před nahrazením argumentů typu, pokud
Mmá větší hloubku genericity ( Genericity oddílu) nežN, odstraňteNze sady.
V opačném případě je volání nejednoznačné a dojde k chybě v době kompilace.
Specifika členů/typů zadaných seznamem argumentů
Člen M je považován za stejně specifický jako N, vzhledem k argument-list A, pokud jsou jejich podpisy stejné nebo pokud každý typ parametru M je stejný jako odpovídající typ parametru v N.
Poznámka. Dva členové můžou skončit ve skupině metod se stejným podpisem kvůli rozšiřujícím metodám. Dva členy mohou být také stejně specifické, ale nemají stejný podpis kvůli parametrům typu nebo rozšíření paramarray.
Člen M je považován za konkrétnější , než N pokud jsou jejich podpisy odlišné a nejméně jeden typ M parametru je konkrétnější než typ parametru v Na žádný typ N parametru není konkrétnější než typ parametru v M. Vzhledem k páru parametrů Mj , Nj který odpovídá argumentu Aj, typ Mj je považován za konkrétnější než typ Nj , pokud je splněna jedna z následujících podmínek:
Existuje rozšiřující převod z typu
Mjna typNj. (Poznámka: Vzhledem k tomu, že se typy parametrů porovnávají bez ohledu na skutečný argument v tomto případě, rozšíření převodu z konstantních výrazů na číselný typ, do kterého hodnota zapadá, se v tomto případě nepovažuje.)Ajje literál0,Mjje číselný typ aNjje výčtový typ. (Poznámka: Toto pravidlo je nezbytné, protože literál0se rozšiřuje na jakýkoli výčtový typ. Vzhledem k tomu, že výčtový typ se rozšiřuje na jeho základní typ, znamená to, že rozlišení0přetížení bude ve výchozím nastavení upřednostňovat výčtové typy než číselné typy. Obdrželi jsme spoustu zpětné vazby, že toto chování bylo neintuitivní.)MjaNjjsou oba číselné typy aMjjsou dřívější nežNjv seznamuByte,SByte, ,Short,UShort,Integer,UInteger,Long,ULong,DecimalSingle, .Double(Poznámka: Pravidlo o číselných typech je užitečné, protože znaménka a nepodepsané číselné typy určité velikosti mají pouze zužující převody mezi nimi. Výše uvedené pravidlo rozdělí vazby mezi těmito dvěma typy ve prospěch "přirozeného" číselného typu. To je zvlášť důležité, když provádíte rozlišení přetížení u typu, který rozšiřuje jak znaménka, tak i nepodepsané číselné typy konkrétní velikosti, například číselný literál, který se vejde do obou typů.)MjaNjjsou typy funkcí delegáta a návratovýMjtyp je konkrétnější než návratovýNjtyp IfAjje klasifikovaný jako metoda lambda aMjneboNjjeSystem.Linq.Expressions.Expression(Of T), pak typ argumentu typu (za předpokladu, že se jedná o typ delegáta) se nahradí porovnávaným typem.Mjje identický s typemAj, aNjnení. (Poznámka: Je zajímavé si uvědomit, že předchozí pravidlo se mírně liší od jazyka C#, v tom jazyce C# vyžaduje, aby typy funkcí delegáta měly před porovnáním návratových typů identické seznamy parametrů, zatímco Visual Basic ne.)
Obecná úroveň
M Člen je určen jako méně obecný než člen N následujícím způsobem:
- Pokud je pro každou dvojici odpovídajících parametrů
MjmenšíMjNjnebo stejně obecný nežNju parametrů typu v metodě a nejméně jedenMjje méně obecný s ohledem na parametry typu v metodě. - V opačném případě, pokud pro každou dvojici odpovídajících parametrů a , je menší nebo stejně obecný než
Njs ohledem na typ parametry typu, a alespoň jedenMjje méně obecný s ohledem na parametry typu typu, pakMje méně obecný nežN.MjNjMj
M Parametr je považován za stejně obecný pro parametrN, pokud jejich typy Mt a Nt oba odkazují na parametry typu nebo oba neodkazují na parametry typu.
M je považován za méně obecný, než N pokud Mt neodkazuje na parametr typu a Nt ne.
Například:
Class C1(Of T)
Sub S1(Of U)(x As U, y As T)
End Sub
Sub S1(Of U)(x As U, y As U)
End Sub
Sub S2(x As Integer, y As T)
End Sub
Sub S2(x As T, y As T)
End Sub
End Class
Module Test
Sub Main()
Dim x As C1(Of Integer) = New C1(Of Integer)
x.S1(10, 10) ' Calls S1(U, T)
x.S2(10, 10) ' Calls S2(Integer, T)
End Sub
End Module
Parametry typu rozšiřující metody, které byly opraveny během kariování, se považují za parametry typu typu, nikoli parametry typu metody. Například:
Imports System.Runtime.CompilerServices
Module Ext1
<Extension> _
Sub M1(Of T, U)(x As T, y As U, z As U)
End Sub
End Module
Module Ext2
<Extension> _
Sub M1(Of T, U)(x As T, y As U, z As T)
End Sub
End Module
Module Test
Sub Main()
Dim i As Integer = 10
i.M1(10, 10)
End Sub
End Module
Hloubka genericity
M Člen je určen, aby měl větší hloubku genericity než členN, pokud, pro každou dvojici shodných parametrů Mj a Nj, Mj má větší nebo stejnou hloubku genericity než Nja alespoň jeden Mj je větší hloubkou genericity. Hloubka genericity je definována takto:
Cokoli jiného než parametr typu má větší hloubku genericity než parametr typu;
Rekurzivně má vytvořený typ větší hloubku genericity než jiný konstruovaný typ (se stejným počtem argumentů typu), pokud alespoň jeden argument typu má větší hloubku genericity a žádný argument typu nemá menší hloubku než odpovídající argument typu v druhém argumentu.
Typ pole má větší hloubku genericity než jiný typ pole (se stejným počtem dimenzí), pokud typ prvku prvního má větší hloubku genericity než typ prvku druhého.
Například:
Module Test
Sub f(Of T)(x As Task(Of T))
End Sub
Sub f(Of T)(x As T)
End Sub
Sub Main()
Dim x As Task(Of Integer) = Nothing
f(x) ' Calls the first overload
End Sub
End Module
Použitelnost seznamu argumentů
Metoda je použitelná pro sadu argumentů typu, pozičních argumentů a pojmenovaných argumentů, pokud lze metodu vyvolat pomocí seznamů argumentů. Seznamy argumentů se shodují se seznamy parametrů následujícím způsobem:
- Nejprve se shodujte s jednotlivými pozičními argumenty v seznamu parametrů metody. Pokud existuje více pozičních argumentů než parametrů a poslední parametr není paramarray, metoda není použitelná. V opačném případě je parametr paramarray rozšířen o parametry typu elementu paramarray tak, aby odpovídaly počtu pozičních argumentů. Pokud je poziční argument vynechán, který by šel do paramarray, metoda není použitelná.
- Dále se shodujte s každým pojmenovaným argumentem s parametrem s daným názvem. Pokud se některý z pojmenovaných argumentů neshoduje, odpovídá parametru paramarray nebo odpovídá argumentu, který je již shodný s jiným pozičním nebo pojmenovaným argumentem, metoda se nepoužije.
- Dále, pokud byly zadány argumenty typu, jsou porovnána se seznamem parametrů typu . Pokud dva seznamy nemají stejný počet prvků, metoda není použitelná, pokud seznam argumentů typu není prázdný. Pokud je seznam argumentů typu prázdný, použije se k vyzkoušení a odvození seznamu argumentů typu. Pokud se odvozování typu nezdaří, metoda se nedá použít. V opačném případě jsou argumenty typu vyplněny místo parametrů typu v podpisu. Pokud parametry, které nebyly spárovány, nejsou volitelné, metoda není použitelná.
- Pokud výrazy argumentu nejsou implicitně konvertibilní na typy parametrů, které odpovídají, pak metoda není použitelná.
- Pokud je parametr ByRef a neexistuje implicitní převod z typu parametru na typ argumentu, pak metoda není použitelná.
- Pokud argumenty typu porušují omezení metody (včetně odvozených argumentů typu z kroku 3), metoda není použitelná. Například:
Module Module1
Sub Main()
f(Of Integer)(New Exception)
' picks the first overload (narrowing),
' since the second overload (widening) violates constraints
End Sub
Sub f(Of T)(x As IComparable)
End Sub
Sub f(Of T As Class)(x As Object)
End Sub
End Module
Pokud výraz s jedním argumentem odpovídá parametru paramarray a typ výrazu argumentu je převoditelný na typ parametru paramarray i typ elementu paramarray, je metoda použitelná ve svých rozbalených i nevyexpandovaných formulářích se dvěma výjimkami. Pokud je převod z typu výrazu argumentu na typ paramarray zužující, je metoda použitelná pouze ve své rozšířené podobě. Pokud je výraz argumentu literál Nothing, pak metoda je použitelná pouze ve své nevyexpandované podobě. Například:
Module Test
Sub F(ParamArray a As Object())
Dim o As Object
For Each o In a
Console.Write(o.GetType().FullName)
Console.Write(" ")
Next o
Console.WriteLine()
End Sub
Sub Main()
Dim a As Object() = { 1, "Hello", 123.456 }
Dim o As Object = a
F(a)
F(CType(a, Object))
F(o)
F(CType(o, Object()))
End Sub
End Module
Výše uvedený příklad vytvoří následující výstup:
System.Int32 System.String System.Double
System.Object[]
System.Object[]
System.Int32 System.String System.Double
V prvním a posledním vyvolání F, normální forma F je použitelná, protože rozšiřující převod existuje z typu argumentu na typ parametru (oba jsou typu Object()) a argument se předává jako normální parametr hodnoty. Ve druhém a třetím vyvolání není normální forma F použitelná, protože neexistuje rozšiřující převod z typu argumentu na typ parametru (převody z Object na Object() zúžení). Rozšířená forma F je však použitelná a vyvolání vytvoří jeden prvek Object() . Jeden prvek pole je inicializován s danou hodnotou argumentu (což je samotný odkaz na ).Object()
Předávání argumentů a výběr argumentů pro volitelné parametry
Pokud je parametrem hodnota, musí být odpovídající výraz argumentu klasifikován jako hodnota. Hodnota se převede na typ parametru a předá se jako parametr za běhu. Pokud je parametr referenčním parametrem a odpovídající výraz argumentu je klasifikován jako proměnná, jejíž typ je stejný jako parametr, pak je odkaz na proměnnou předán jako parametr za běhu.
V opačném případě, pokud je odpovídající výraz argumentu klasifikován jako proměnná, hodnota nebo přístup k vlastnosti, je přidělena dočasná proměnná typu parametru. Před vyvoláním metody za běhu je výraz argumentu přetříděn jako hodnota, převeden na typ parametru a přiřazen k dočasné proměnné. Potom se jako parametr předá odkaz na dočasnou proměnnou. Po vyhodnocení vyvolání metody je výraz argumentu klasifikován jako proměnná nebo přístup k vlastnosti, je dočasná proměnná přiřazena k výrazu proměnné nebo výrazu přístupu k vlastnosti. Pokud přístupový výraz vlastnosti nemá žádné Set přístupové objekty, přiřazení se neprovede.
Pro volitelné parametry, ve kterých nebyl argument zadán, kompilátor vybere argumenty, jak je popsáno níže. Ve všech případech testuje typ parametru po nahrazení obecného typu.
Pokud volitelný parametr má atribut
System.Runtime.CompilerServices.CallerLineNumbera vyvolání je z umístění ve zdrojovém kódu a číselný literál představující číslo řádku daného umístění má vnitřní převod na typ parametru, použije se číselný literál. Pokud vyvolání zahrnuje více řádků, pak výběr řádku, který se má použít, je závislý na implementaci.Pokud volitelný parametr má atribut
System.Runtime.CompilerServices.CallerFilePatha vyvolání je z umístění ve zdrojovém kódu a řetězcový literál představující cestu k souboru umístění má vnitřní převod na typ parametru, použije se řetězcový literál. Formát cesty k souboru je závislý na implementaci.Pokud volitelný parametr má atribut
System.Runtime.CompilerServices.CallerMemberNamea vyvolání je v těle člena typu nebo v atributu použitém pro libovolnou část tohoto členu typu a řetězcový literál představující tento název členu má vnitřní převod na typ parametru, použije se řetězcový literál. Pro vyvolání, které jsou součástí přístupových objektů vlastností nebo vlastních obslužných rutin událostí, pak použitý název členu je název vlastnosti nebo samotné události. Pro vyvolání, které jsou součástí operátoru nebo konstruktoru, se použije název specifický pro implementaci.
Pokud žádná z výše uvedených možností neplatí, použije se výchozí hodnota volitelného parametru (nebo Nothing pokud není zadána žádná výchozí hodnota). A pokud platí více než jedna z výše uvedených možností, pak volba, kterou použít, je závislá na implementaci.
Atributy CallerLineNumber a CallerFilePath atributy jsou užitečné pro protokolování. To CallerMemberName je užitečné pro implementaci INotifyPropertyChanged. Tady jsou příklady.
Sub Log(msg As String,
<CallerFilePath> Optional file As String = Nothing,
<CallerLineNumber> Optional line As Integer? = Nothing)
Console.WriteLine("{0}:{1} - {2}", file, line, msg)
End Sub
WriteOnly Property p As Integer
Set(value As Integer)
Notify(_p, value)
End Set
End Property
Private _p As Integer
Sub Notify(Of T As IEquatable(Of T))(ByRef v1 As T, v2 As T,
<CallerMemberName> Optional prop As String = Nothing)
If v1 IsNot Nothing AndAlso v1.Equals(v2) Then Return
If v1 Is Nothing AndAlso v2 Is Nothing Then Return
v1 = v2
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(prop))
End Sub
Kromě výše uvedených volitelných parametrů microsoft Visual Basic rozpozná také některé další volitelné parametry, pokud jsou importovány z metadat (tj. z odkazu na knihovnu DLL):
Při importu z metadat používá Visual Basic také parametr
<Optional>jako indikující, že parametr je volitelný: tímto způsobem je možné importovat deklaraci, která má volitelný parametr, ale žádnou výchozí hodnotu, i když se nedá vyjádřit pomocí klíčovéhoOptionalslova.Pokud má volitelný parametr atribut
Microsoft.VisualBasic.CompilerServices.OptionCompareAttributea číselný literál 1 nebo 0 má převod na typ parametru, kompilátor použije jako argument literál 1, pokudOption Compare Textje v platnosti, nebo literál 0, pokudOptional Compare Binaryje v platnosti.Pokud volitelný parametr má atribut
System.Runtime.CompilerServices.IDispatchConstantAttributea má typObjecta nezadá výchozí hodnotu, kompilátor použije argumentNew System.Runtime.InteropServices.DispatchWrapper(Nothing).Pokud volitelný parametr má atribut
System.Runtime.CompilerServices.IUnknownConstantAttributea má typObjecta nezadá výchozí hodnotu, kompilátor použije argumentNew System.Runtime.InteropServices.UnknownWrapper(Nothing).Pokud volitelný parametr má typ
Objecta nezadá výchozí hodnotu, kompilátor použije argumentSystem.Reflection.Missing.Value.
Podmíněné metody
Pokud cílová metoda, na kterou výraz vyvolání odkazuje, je podprogram, který není členem rozhraní a pokud má metoda jeden nebo více System.Diagnostics.ConditionalAttribute atributů, vyhodnocení výrazu závisí na konstantách podmíněné kompilace definované v tomto okamžiku ve zdrojovém souboru. Každá instance atributu určuje řetězec, který pojmenuje konstantu podmíněné kompilace. Každá konstanta podmíněné kompilace se vyhodnotí jako součást příkazu podmíněné kompilace. Pokud se konstanta vyhodnotí jako True, výraz se vyhodnotí normálně za běhu. Pokud se konstanta vyhodnotí jako False, výraz se vůbec nevyhodnotí.
Při hledání atributu je kontrolována nejvíce odvozená deklarace přepisovatelné metody.
Poznámka. Atribut není platný pro funkce nebo metody rozhraní a je ignorován, pokud je zadán u některého typu metody. Podmíněné metody se tedy zobrazí pouze ve vyvolání příkazů.
Odvození argumentu typu
Pokud je volána metoda s parametry typu bez zadání argumentů typu, typ argument odvození se používá k pokusu a odvození argumentů typu pro volání. To umožňuje použití přirozenější syntaxe pro volání metody s parametry typu, když argumenty typu lze triviálně odvodit. Například s ohledem na následující deklaraci metody:
Module Util
Function Choose(Of T)(b As Boolean, first As T, second As T) As T
If b Then
Return first
Else
Return second
End If
End Function
End Class
Metodu Choose je možné vyvolat bez explicitního zadání argumentu typu:
' calls Choose(Of Integer)
Dim i As Integer = Util.Choose(True, 5, 213)
' calls Choose(Of String)
Dim s As String = Util.Choose(False, "a", "b")
Prostřednictvím odvození argumentu typu jsou argumenty Integer typu a String jsou určeny z argumentů do metody.
Odvození argumentu typu nastane před provedením přetřídění výrazu u metod lambda nebo ukazatelů metody v seznamu argumentů, protože změna klasifikace těchto dvou druhů výrazů může vyžadovat, aby byl typ parametru znám. Vzhledem k sadě argumentů A1,...,An, sada shodných parametrů P1,...,Pn a sada parametrů T1,...,Tntypu metody , závislosti mezi argumenty a parametry typu metody jsou nejprve shromažďovány následujícím způsobem:
Pokud
Anje literálNothing, nevygenerují se žádné závislosti.Pokud
Anje metoda lambda a typPnje konstruovaný typ delegáta neboSystem.Linq.Expressions.Expression(Of T), kdeTje konstruovaný typ delegáta,Pokud typ parametru metody lambda bude odvozen z typu odpovídajícího parametru
Pna typ parametru závisí na parametruTntypu metody , pakAnmá závislost naTn.Pokud je zadán typ parametru metody lambda a typ odpovídajícího parametru
Pnzávisí na parametruTntypu metody , pakTnmá závislost naAn.Pokud návratový
Pntyp závisí na parametruTntypu metody , pakTnmá závislost naAn.Pokud
Anje ukazatel metody a typPnje konstruovaný typ delegáta,Pokud návratový
Pntyp závisí na parametruTntypu metody , pakTnmá závislost naAn.Pokud
Pnje vytvořený typ a typPnzávisí na parametruTntypu metody , pakTnmá závislost naAn.Jinak se nevygeneruje žádná závislost.
Po shromáždění závislostí se eliminují všechny argumenty, které nemají žádné závislosti. Pokud některé parametry typu metody nemají žádné odchozí závislosti (tj. parametr typu metody nezávisí na argumentu), odvození typu selže. V opačném případě se zbývající argumenty a parametry typu metody seskupí do silně propojených komponent. Silně propojená komponenta je sada argumentů a parametrů typu metody, kde jakýkoli prvek v komponentě je dosažitelný prostřednictvím závislostí na jiných prvcích.
Silně propojené komponenty jsou pak topologické a zpracovávané v topologickém pořadí:
Pokud součást silného typu obsahuje pouze jeden prvek,
Pokud už byl prvek označený jako dokončený, přeskočte ho.
Pokud je element argumentem, přidejte z argumentu do parametrů typu metody, které na něm závisí, a označte prvek jako dokončený. Pokud je argument metodou lambda s parametry, které stále potřebují odvozené typy, odvozujte
Objectje pro typy těchto parametrů.Pokud je element parametrem typu metody, odvozujte parametr typu metody jako dominantní typ mezi rady typu argumentu a označte prvek jako dokončený. Pokud má nápověda typu omezení prvku pole, pak se považují pouze převody platné mezi poli daného typu (tj. kovariantní a vnitřní převody polí). Pokud je u nápovědy typu omezení obecného argumentu, zvažují se pouze převody identit. Pokud nelze zvolit žádný dominantní typ, odvození selže. Pokud některé typy argumentů metody lambda závisí na tomto parametru typu metody, typ se rozšíří do metody lambda.
Pokud součást silného typu obsahuje více než jeden prvek, komponenta obsahuje cyklus.
Pro každý parametr typu metody, který je prvkem v komponentě, pokud parametr typu metody závisí na argumentu, který není označen jako dokončený, převeďte tuto závislost na kontrolní výraz, který bude zkontrolován na konci procesu odvozování.
Restartujte proces odvození v okamžiku určení komponent silného typu.
Pokud odvození typu proběhne úspěšně pro všechny parametry typu metody, zkontrolují se všechny závislosti, které byly změněny na kontrolní výrazy. Kontrolní výraz je úspěšný, pokud je typ argumentu implicitně konvertibilní na odvozený typ parametru typu metody. Pokud kontrolní výraz selže, funkce odvození argumentu typu selže.
Při zadání typu Ta argumentu pro argument A a typ Tp parametru pro parametr Pse vygenerují rady typu následujícím způsobem:
Pokud
Tpnezahrnuje žádné parametry typu metody, nebudou generovány žádné rady.Pokud
TpaTajsou typy polí stejného pořadí, nahraďteTaaTpnahraďte typyTaprvků aTprestartujte tento proces omezením prvku pole.Pokud
Tpje parametr typu metody, přidáTase jako tip typu s aktuálním omezením, pokud existuje.Pokud
Aje metoda lambda aTpje vytvořený typ delegáta neboSystem.Linq.Expressions.Expression(Of T), kdeTje konstruovaný typ delegáta, pro každý typ parametruTLmetody lambda a odpovídající typTDparametru delegáta , nahraďteTaTLaTpTDrestartujte proces bez omezení. Potom nahraďteTanávratovým typem metody lambda a:- pokud
Aje běžná metoda lambda, nahraďteTpnávratovým typem typu delegáta; - pokud
Aje asynchronní lambda metoda a návratový typ delegáta má formulářTask(Of T)pro některéT, nahraditTptímtoT; - pokud
Aje metoda lambda iterátoru a návratový typ delegáta má formulářIEnumerator(Of T)neboIEnumerable(Of T)pro některéT, nahraďteTphoT. - V dalším kroku restartujte proces bez omezení.
- pokud
Pokud
Aje ukazatel metody aTpje konstruovaný typ delegáta, použijte typyTpparametrů k určení, která metoda odkazuje nejvíce naTp. Pokud existuje metoda, která je nejvhodnější, nahraďteTanávratovým typem metody aTpnávratovým typem typu delegáta a restartujte proces bez omezení.TpJinak musí být konstruovaný typ. Vzhledem kTGobecnémuTptypu ,Pokud
TajeTG, dědí zTG, nebo implementuje typTGpřesně jednou, pak pro každý odpovídající typ argumentTaxzTaaTpxzTp, nahraditTaTaxaTpTpxrestartovat proces omezením obecného argumentu.V opačném případě se pro obecnou metodu nezdaří odvození typu.
Úspěch odvození typu nezaručuje, že metoda je použitelná a sama o sobě.
Visual Basic language spec