Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
I praktiken är reglerna för att fastställa överbelastningsmatchning avsedda att hitta den överlagring som är "närmast" de faktiska argument som anges. Om det finns en metod vars parametertyper matchar argumenttyperna är den metoden uppenbarligen närmast. Bortsett från detta är en metod närmare än en annan om alla dess parametertyper är smalare än (eller samma som) parametertyperna för den andra metoden. Om ingen av metodens parametrar är smalare än den andra finns det inget sätt att avgöra vilken metod som ligger närmare argumenten.
Observera. Överlagringsmatchning tar inte hänsyn till metodens förväntade returtyp.
Observera också att på grund av den namngivna parametersyntaxen kanske ordningen på de faktiska och formella parametrarna inte är densamma.
Med en metodgrupp bestäms den mest tillämpliga metoden i gruppen för en argumentlista med hjälp av följande steg. Om inga medlemmar finns kvar i uppsättningen efter att ett visst steg har tillämpats uppstår ett kompileringsfel. Om endast en medlem finns kvar i uppsättningen är den medlemmen den mest tillämpliga medlemmen. Stegen är:
Om inga typargument har angetts tillämpar du först typinferens på metoder som har typparametrar. Om typinferens lyckas för en metod används argument av härledda typer för den specifika metoden. Om typinferens misslyckas för en metod elimineras den metoden från uppsättningen.
Ta sedan bort alla medlemmar från uppsättningen som är otillgängliga eller inte tillämpliga (avsnitt tillämplig till argumentlista) i argumentlistan
Om ett eller flera argument är
AddressOfeller lambda-uttryck beräknar du sedan de delegerade avslappningsnivåerna för varje sådant argument enligt nedan. Om den sämsta (lägsta) delegatavslappningsnivån iNär sämre än den lägsta delegerade avslappningsnivån iMeliminerarNdu från uppsättningen. De delegerade avslappningsnivåerna är följande:Fel på avslappningsnivå för ombud – om
AddressOflambda inte kan konverteras till ombudstypen.Begränsad delegatavslappning av returtyp eller parametrar – om argumentet är
AddressOfeller en lambda med en deklarerad typ och konverteringen från dess returtyp till delegatreturtypen minskar, eller om argumentet är en vanlig lambda och konverteringen från något av dess returuttryck till delegatreturtypen minskar, eller om argumentet är en asynkron lambda och ombudets returtyp ärTask(Of T)och konverteringen från något av dess returuttryck tillTminskar, eller om argumentet är en iterator lambda och delegatreturtypenIEnumerator(Of T)ellerIEnumerable(Of T)och konverteringen från någon av dess avkastningsopernder tillTminskar.Breddning av ombudsavslappning till ombud utan signatur – om ombudstypen är
System.DelegateellerSystem.MultiCastDelegateSystem.Object.Drop return or arguments delegate relax – om argumentet är
AddressOfeller en lambda med en deklarerad returtyp och delegattypen saknar en returtyp, eller om argumentet är en lambda med ett eller flera returuttryck och delegattypen saknar en returtyp, eller om argumentet ärAddressOfeller lambda utan parametrar och ombudstypen har parametrar.Breddning av delegatavslappning av returtyp – om argumentet är
AddressOfeller en lambda med en deklarerad returtyp, och det finns en bredare konvertering från dess returtyp till ombudets, eller om argumentet är en vanlig lambda där konverteringen från alla returuttryck till delegatreturtypen breddas eller identiteten med minst en breddning, eller om argumentet är en asynkron lambda och ombudet ärTask(Of T)ellerTaskoch konverteringen från alla returuttryck tillT/Objectbreddar eller identiteter med minst en breddning, eller om argumentet är en iterator lambda och ombudet ärIEnumerator(Of T)ellerIEnumerable(Of T)ellerIEnumeratorellerIEnumerableoch konverteringen från alla returuttryck tillT/Objectutvidgas eller identiteten med minst en breddning.Avslappning av identitetsdelegat – om argumentet är en
AddressOfeller en lambda som matchar ombudet exakt, utan att utvidga eller minska eller släppa parametrar eller returer eller avkastningar. Om vissa medlemmar i uppsättningen inte kräver att begränsade konverteringar ska tillämpas på något av argumenten eliminerar du sedan alla medlemmar som gör det. Till exempel:
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ärefter utförs eliminering baserat på minskning enligt följande. (Observera att om Alternativet strikt är På har alla medlemmar som kräver begränsning redan bedömts vara otillämpbara (avsnitt tillämplighet till argumentlista) och tagits bort i steg 2.)
- Om vissa instansmedlemmar i uppsättningen bara kräver begränsade konverteringar där argumentuttryckstypen är
Objecteliminerar du alla andra medlemmar. - Om uppsättningen innehåller mer än en medlem som endast kräver en begränsning från
Object, omklassificeras anropsmåluttrycket som en sen bindningsmetodåtkomst (och ett fel anges om typen som innehåller metodgruppen är ett gränssnitt eller om någon av de tillämpliga medlemmarna var tilläggsmedlemmar). - Om det finns kandidater som bara kräver att numeriska literaler begränsas väljer du den mest specifika bland alla återstående kandidater enligt stegen nedan. Om vinnaren endast behöver begränsas från numeriska literaler väljs den som ett resultat av överbelastningsmatchning. annars är det ett fel.
Observera. Motiveringen för den här regeln är att om ett program är löst skrivet (dvs. de flesta eller alla variabler deklareras som
Object), kan överlagringsmatchning vara svårt när många konverteringar frånObjectminskar. I stället för att överbelastningsmatchningen misslyckas i många situationer (kräver stark typning av argumenten till metodanropet) skjuts lösningen av lämplig överbelastad metod för anrop upp till körningstiden. Detta gör att det löst skrivna anropet kan lyckas utan ytterligare gjutningar. En olycklig bieffekt av detta är dock att för att utföra det sena anropet måste anropsmålet gjutas tillObject. När det gäller ett strukturvärde innebär det att värdet måste boxas till ett tillfälligt värde. Om metoden som så småningom anropas försöker ändra ett fält i strukturen går den här ändringen förlorad när metoden returneras. Gränssnitt undantas från den här specialregeln eftersom sen bindning alltid matchar medlemmarna i körningsklassen eller strukturtypen, som kan ha andra namn än medlemmarna i de gränssnitt som de implementerar.- Om vissa instansmedlemmar i uppsättningen bara kräver begränsade konverteringar där argumentuttryckstypen är
Om några instansmetoder finns kvar i uppsättningen som inte kräver en förträngning eliminerar du sedan alla tilläggsmetoder från uppsättningen. Till exempel:
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 ModuleObservera. Tilläggsmetoder ignoreras om det finns tillämpliga instansmetoder för att garantera att tillägg av en import (som kan föra in nya tilläggsmetoder i omfånget) inte leder till att ett anrop på en befintlig instansmetod binds om till en tilläggsmetod. Med tanke på det breda omfånget för vissa tilläggsmetoder (dvs. de som definieras i gränssnitt och/eller typparametrar) är detta en säkrare metod för bindning till tilläggsmetoder.
Om, med tanke på två medlemmar i uppsättningen
MochN,Mär mer specifik ( avsnittsspecifikhet för medlemmar/typer givet en argumentlista) änNmed tanke på argumentlistan, eliminerar duNfrån uppsättningen. Om fler än en medlem finns kvar i uppsättningen och de återstående medlemmarna inte är lika specifika med tanke på argumentlistan, resulterar ett kompileringsfel.Annars, med tanke på två medlemmar i uppsättningen,
MochN, tillämpar följande regler för bindningsbrott i ordning:Om
Minte har en ParamArray-parameter menNgör det, eller om båda gör det menMskickar färre argument till paramArray-parametern änNvad som gör det, eliminerarNdu från uppsättningen. Till exempel: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 ModuleExemplet ovan ger följande utdata:
F(Object, Object()) F(Object, Object, Object()) F(Object, Object, Object()) G(Object)Observera. När en klass deklarerar en metod med en paramarrayparameter är det inte ovanligt att även inkludera några av de expanderade formulären som vanliga metoder. På så sätt är det möjligt att undvika allokeringen av en matrisinstans som inträffar när en expanderad form av en metod med en paramarray-parameter anropas.
Om
Mdefinieras i en mer härledd typ änNeliminerar duNfrån uppsättningen. Till exempel: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 ModuleDen här regeln gäller även för de typer som tilläggsmetoder definieras på. Till exempel:
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 ModuleOm
MochNär tilläggsmetoder och måltypenMför är en klass eller struktur och måltypenNför är ett gränssnitt eliminerar duNfrån uppsättningen. Till exempel: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 ModuleOm
MochNär tilläggsmetoder, och måltypen förMochNär identiska efter typparameterersättning, och måltypen för före typparameterersättningMinte innehåller typparametrar, men måltypen förNhar då färre typparametrar än måltypenNför , elimineraNfrån uppsättningen. Till exempel: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 ModuleInnan typargument har ersatts, om
Mär mindre generiska (avsnitt generiska) änN, elimineraNfrån uppsättningen.Om
Minte är en tilläggsmetod ochNär eliminerar duNfrån uppsättningen.Om
MochNär tilläggsmetoder ochMhittades föreN(Section Extension Method Collection) eliminerar duNfrån uppsättningen. Till exempel: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 NamespaceOm tilläggsmetoderna hittades i samma steg är dessa tilläggsmetoder tvetydiga. Anropet kan alltid vara tvetydigt med hjälp av namnet på standardmodulen som innehåller tilläggsmetoden och anropar tilläggsmetoden som om den var en vanlig medlem. Till exempel:
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 ModuleOm
MochNbåda nödvändiga typinferenser för att generera typargument ochMinte krävde att den dominerande typen skulle bestämmas för något av dess typargument (dvs. var och en av de typargument som härleds till en enda typ), menNelimineradeNfrån uppsättningen.Observera. Den här regeln säkerställer att överbelastningsmatchning som lyckades i tidigare versioner (där slutsatsdragning av flera typer för ett typargument skulle orsaka ett fel) fortsätter att ge samma resultat.
Om överbelastningsmatchning görs för att matcha målet för ett uttryck för att skapa ombud från ett
AddressOfuttryck, och både ombudet ochMär funktioner medanNär en underrutin, eliminerar duNfrån uppsättningen. På samma sätt, om både ombudet ochMär subrutiner, medanNär en funktion, eliminerar duNfrån uppsättningen.Om
Minte använde några valfria parameterstandarder i stället för explicita argument, menNgjorde det, eliminerarNdu från uppsättningen.Innan typargument har ersatts, om
Mhar större djup av generiskitet (section genericity) änN, eliminerarNdu sedan från uppsättningen.
Annars är anropet tvetydigt och ett kompileringsfel inträffar.
Specificitet för medlemmar/typer med tanke på en argumentlista
En medlem M anses vara lika specifik som N, med tanke på en argumentlista A, om deras signaturer är desamma eller om varje parametertyp i M är samma som motsvarande parametertyp i N.
Observera. Två medlemmar kan hamna i en metodgrupp med samma signatur på grund av tilläggsmetoder. Två medlemmar kan också vara lika specifika men inte ha samma signatur på grund av typparametrar eller paramarrayexpansion.
En medlem M anses vara mer specifik än N om deras signaturer är olika och minst en parametertyp i M är mer specifik än en parametertyp i N, och ingen parametertyp i N är mer specifik än en parametertyp i M. Med tanke på ett par parametrar Mj och Nj som matchar ett argument Ajanses typen av Mj vara mer specifik än typen av Nj om något av följande villkor är sant:
Det finns en bredare konvertering från typen av
Mjtill typenNj. (Obs! Eftersom parametertyper jämförs utan hänsyn till det faktiska argumentet i det här fallet beaktas inte den bredare konverteringen från konstanta uttryck till en numerisk typ som värdet passar in i i det här fallet.)Ajär literalen0,Mjär en numerisk typ ochNjär en uppräknad typ. (Obs! Den här regeln är nödvändig eftersom literalen0vidgas till alla uppräknade typer. Eftersom en uppräknad typ vidgas till den underliggande typen innebär det att överbelastningsupplösning på0som standard föredrar uppräknade typer framför numeriska typer. Vi fick mycket feedback om att det här beteendet var kontraintuitivt.)MjochNjär båda numeriska typer ochMjkommer tidigare änNji listanByte, ,ShortSByte, ,IntegerUShort, ,UInteger,Long,ULong,Decimal, ,Single,Double. (Obs! Regeln om de numeriska typerna är användbar eftersom de signerade och osignerade numeriska typerna av en viss storlek bara har smala konverteringar mellan sig. Ovanstående regel bryter oavgjort mellan de två typerna till förmån för den mer "naturliga" numeriska typen. Detta är särskilt viktigt när du utför överbelastningsmatchning på en typ som vidgas till både signerade och osignerade numeriska typer av en viss storlek, till exempel en numerisk literal som passar in i båda.)MjochNjär delegerade funktionstyperMjoch returtypen är mer specifik än returtypenNjIfAjklassificeras som en lambda-metod, ochMjellerNjärSystem.Linq.Expressions.Expression(Of T), ersätts typargumentet för typen (förutsatt att det är en ombudstyp) för den typ som jämförs.Mjär identisk med typen ,AjochNjär inte det. (Obs! Det är intressant att notera att den tidigare regeln skiljer sig något från C#, eftersom C# kräver att de delegerade funktionstyperna har identiska parameterlistor innan du jämför returtyper, medan Visual Basic inte gör det.)
Generiskhet
En medlem M är fast besluten att vara mindre generisk än en medlem N enligt följande:
- Om, för varje par med matchande parametrar
MjochNj,Mjär mindre eller lika generiskt änNjmed avseende på typparametrar på metoden, och minst ettMjär mindre generiskt när det gäller typparametrar på metoden. - Annars, om för varje par med matchande parametrar
MjochNj,Mjär mindre eller lika generiskt änNjmed avseende på typparametrar på typen, och minst ettMjär mindre generiskt när det gäller typparametrar på typen, är det mindreMgeneriskt änN.
En parameter M anses vara lika generisk för en parameter N om deras typer Mt och Nt båda refererar till typparametrar eller båda inte refererar till typparametrar.
M anses vara mindre allmänt än N om Mt inte refererar till en typparameter och Nt gör det.
Till exempel:
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
Tilläggsmetodtypparametrar som korrigerades under currying anses vara typparametrar för typen, inte typparametrar på metoden. Till exempel:
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
Generell djup
En medlem M är fast besluten att ha större djup av generiskitet än en medlem N om, för varje par med matchande parametrar Mj och Nj, Mj har större eller lika djup av generiskhet än Nj, och minst en Mj har större djup av generiskitet. Generell djup definieras på följande sätt:
Allt annat än en typparameter har större djup av generiskitet än en typparameter.
Rekursivt har en konstruerad typ större djup av generiskitet än en annan konstruerad typ (med samma antal typargument) om minst ett typargument har större djup av generiskitet och inget typargument har mindre djup än motsvarande typargument i den andra.
En matristyp har större djup av generiskitet än en annan matristyp (med samma antal dimensioner) om elementtypen för den första har större generalitetsdjup än elementtypen för den andra.
Till exempel:
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
Tillämplighet för argumentlista
En metod gäller för en uppsättning typargument, positionsargument och namngivna argument om metoden kan anropas med hjälp av argumentlistorna. Argumentlistorna matchas mot parameterlistorna på följande sätt:
- Matcha först varje positionsargument i ordning med listan över metodparametrar. Om det finns fler positionsargument än parametrar och den sista parametern inte är en paramarray är metoden inte tillämplig. Annars expanderas parametern paramarray med parametrar av elementtypen paramarray för att matcha antalet positionsargument. Om ett positionsargument utelämnas som skulle gå in i en paramarray är metoden inte tillämplig.
- Matcha sedan varje namngivet argument med en parameter med det angivna namnet. Om ett av de namngivna argumenten inte matchar, matchar en paramarrayparameter eller matchar ett argument som redan matchats med ett annat positionellt eller namngivet argument, är metoden inte tillämplig.
- Om typargument har angetts matchas de sedan mot typparameterlistan . Om de två listorna inte har samma antal element är metoden inte tillämplig, såvida inte argumentlistan av typen är tom. Om typargumentlistan är tom används typinferens för att försöka härleda typargumentlistan. Om inferensen av typen misslyckas är metoden inte tillämplig. Annars fylls typargumenten i stället för typparametrarna i signaturen. Om parametrar som inte har matchats inte är valfria är metoden inte tillämplig.
- Om argumentuttrycken inte implicit kan konverteras till de typer av parametrar som de matchar är metoden inte tillämplig.
- Om en parameter är ByRef och det inte finns någon implicit konvertering från parametertypen till argumentets typ, är metoden inte tillämplig.
- Om typargument strider mot metodens begränsningar (inklusive argument av härledd typ från steg 3) är metoden inte tillämplig. Till exempel:
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
Om ett enda argumentuttryck matchar en paramarrayparameter och typen av argumentuttrycket kan konverteras till både typen av parametern paramarray och paramarrayelementtypen, tillämpas metoden i både dess expanderade och oexpandererade former, med två undantag. Om konverteringen från typen av argumentuttrycket till paramarraytypen minskar, är metoden endast tillämplig i dess expanderade form. Om argumentuttrycket är literal Nothinggäller metoden endast i dess oexpandererade form. Till exempel:
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
Exemplet ovan ger följande utdata:
System.Int32 System.String System.Double
System.Object[]
System.Object[]
System.Int32 System.String System.Double
I de första och sista anropen av Fgäller den normala formen av F eftersom det finns en bredare konvertering från argumenttypen till parametertypen (båda är av typen Object()), och argumentet skickas som en vanlig värdeparameter. I den andra och tredje anropen är den normala formen inte F tillämplig eftersom det inte finns någon bredare konvertering från argumenttypen till parametertypen (konverteringarna från Object till Object() minskar). Den utökade formen av F är dock tillämplig och ett ett-element Object() skapas av anropet. Det enskilda elementet i matrisen initieras med det angivna argumentvärdet (som i sig är en referens till en Object()).
Skicka argument och välja argument för valfria parametrar
Om en parameter är en värdeparameter måste det matchande argumentuttrycket klassificeras som ett värde. Värdet konverteras till parametertypen och skickas som parameter vid körning. Om parametern är en referensparameter och det matchande argumentuttrycket klassificeras som en variabel vars typ är samma som parametern skickas en referens till variabeln som parameter vid körning.
Om det matchande argumentuttrycket annars klassificeras som en variabel, ett värde eller en egenskapsåtkomst allokeras en tillfällig variabel av parametertypen. Före metodanropet vid körningen omklassificeras argumentuttrycket som ett värde, konverteras till parametertypen och tilldelas till den tillfälliga variabeln. Sedan skickas en referens till den tillfälliga variabeln som parameter. När metodanropet har utvärderats, om argumentuttrycket klassificeras som en variabel eller egenskapsåtkomst, tilldelas den tillfälliga variabeln till variabeluttrycket eller egenskapsåtkomstuttrycket. Om egenskapsåtkomstuttrycket inte har någon Set accessor utförs inte tilldelningen.
För valfria parametrar där ett argument inte har angetts väljer kompilatorn argument enligt beskrivningen nedan. I samtliga fall testas den mot parametertypen efter generisk typersättning.
Om den valfria parametern har attributet
System.Runtime.CompilerServices.CallerLineNumber, och anropet kommer från en plats i källkoden, och en numerisk literal som representerar platsens radnummer har en inbyggd konvertering till parametertypen, används den numeriska literalen. Om anropet sträcker sig över flera rader är valet av vilken rad som ska användas implementeringsberoende.Om den valfria parametern har attributet
System.Runtime.CompilerServices.CallerFilePath, och anropet kommer från en plats i källkoden, och en strängliteral som representerar den platsens filsökväg har en inbyggd konvertering till parametertypen, används strängliteralen. Filsökvägens format är implementeringsberoende.Om den valfria parametern har attributet
System.Runtime.CompilerServices.CallerMemberName, och anropet finns i brödtexten för en typmedlem eller i ett attribut som tillämpas på någon del av den typen medlem, och en strängliteral som representerar det medlemsnamnet har en inbyggd konvertering till parametertypen, används strängliteralen. För anrop som ingår i egenskapsåtkomster eller anpassade händelsehanterare är medlemsnamnet som används egenskapen eller själva händelsen. För anrop som ingår i en operator eller konstruktor används ett implementeringsspecifikt namn.
Om inget av ovanstående gäller används den valfria parameterns standardvärde (eller Nothing om inget standardvärde anges). Och om mer än ett av ovanstående gäller är valet som ska användas implementeringsberoende.
Attributen CallerLineNumber och CallerFilePath är användbara för loggning.
CallerMemberName Är användbart för att implementera INotifyPropertyChanged. Här är exempel.
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
Förutom de valfria parametrarna ovan identifierar Microsoft Visual Basic även några ytterligare valfria parametrar om de importeras från metadata (dvs. från en DLL-referens):
När du importerar från metadata behandlar Visual Basic även parametern
<Optional>som ett tecken på att parametern är valfri: på så sätt går det att importera en deklaration som har en valfri parameter men inget standardvärde, även om detta inte kan uttryckas med nyckelordetOptional.Om den valfria parametern har attributet
Microsoft.VisualBasic.CompilerServices.OptionCompareAttribute, och den numeriska literalen 1 eller 0 har en konvertering till parametertypen, använder kompilatorn som argument antingen literal 1 omOption Compare Textden är i kraft eller literal 0 omOptional Compare Binaryden är i kraft.Om den valfria parametern har attributet
System.Runtime.CompilerServices.IDispatchConstantAttribute, och den har typenObject, och den inte anger något standardvärde, använder kompilatorn argumentetNew System.Runtime.InteropServices.DispatchWrapper(Nothing).Om den valfria parametern har attributet
System.Runtime.CompilerServices.IUnknownConstantAttribute, och den har typenObject, och den inte anger något standardvärde, använder kompilatorn argumentetNew System.Runtime.InteropServices.UnknownWrapper(Nothing).Om den valfria parametern har typen
Object, och den inte anger något standardvärde, använder kompilatorn argumentetSystem.Reflection.Missing.Value.
Villkorsstyrda metoder
Om målmetoden som ett anropsuttryck refererar till är en underrutin som inte är medlem i ett gränssnitt och om metoden har ett eller flera System.Diagnostics.ConditionalAttribute attribut, beror utvärderingen av uttrycket på de villkorsstyrda kompileringskonstanterna som definierades vid den tidpunkten i källfilen. Varje instans av attributet anger en sträng som namnger en konstant för villkorlig kompilering. Varje konstant för villkorsstyrd kompilering utvärderas som om den ingick i en villkorsstyrd kompileringsinstrukering. Om konstanten utvärderas till Trueutvärderas uttrycket normalt vid körning. Om konstanten utvärderas till Falseutvärderas inte uttrycket alls.
När du letar efter attributet kontrolleras den mest härledda deklarationen av en övergripande metod.
Observera. Attributet är inte giltigt för funktioner eller gränssnittsmetoder och ignoreras om det anges för någon av metoderna. Därför visas villkorsstyrda metoder endast i anropssatser.
Skriv argumentinferens
När en metod med typparametrar anropas utan att ange typargument används typargumentsinferens för att prova och härleda typargument för anropet. Detta gör att en mer naturlig syntax kan användas för att anropa en metod med typparametrar när typargumenten kan härledas trivialt. Till exempel med följande metoddeklaration:
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
det går att anropa Choose metoden utan att uttryckligen ange ett typargument:
' 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")
Genom typargumentets slutsatsdragning, typargumenten Integer och String bestäms från argumenten till metoden.
Typargumentinferens inträffar innan uttrycksomklassificering utförs på lambda-metoder eller metodpekare i argumentlistan, eftersom omklassificering av dessa två typer av uttryck kan kräva att parametertypen är känd. Med tanke på en uppsättning argument A1,...,An, en uppsättning matchande parametrar P1,...,Pn och en uppsättning parametrar T1,...,Tnför metodtyp samlas först beroendena mellan argumenten och metodtypsparametrarna in på följande sätt:
Om
Anär literalenNothinggenereras inga beroenden.Om
Anär en lambda-metod och typen avPnär en konstruerad ombudstyp ellerSystem.Linq.Expressions.Expression(Of T), därTär en konstruerad delegattyp,Om typen av en lambda-metodparameter härleds från typen av motsvarande parameter
Pn, och parametertypen är beroende av en metodtypsparameterTn, har du ettAnberoende avTn.Om typen av en lambda-metodparameter har angetts och vilken typ av motsvarande parameter
Pnsom är beroende av en parameter av metodtypTnhar du ettTnberoende avAn.Om returtypen är beroende av
Pnen metodtypsparameterTnhar duTnett beroende avAn.Om
Anär en metodpekare och typen avPnär en konstruerad ombudstyp,Om returtypen är beroende av
Pnen metodtypsparameterTnhar duTnett beroende avAn.Om
Pnär en konstruerad typ och typen av är beroende avPnen metodtypsparameterTnhar duTnett beroende avAn.Annars genereras inget beroende.
När du har samlat in beroenden elimineras alla argument som inte har några beroenden. Om någon metodtypparametrar inte har några utgående beroenden (dvs. metodtypsparametern inte är beroende av ett argument) misslyckas typinferensen. Annars grupperas de återstående argumenten och metodtypsparametrarna i starkt anslutna komponenter. En starkt ansluten komponent är en uppsättning argument och metodtypsparametrar, där alla element i komponenten kan nås via beroenden för andra element.
De starkt anslutna komponenterna sorteras sedan topologiskt och bearbetas i topologisk ordning:
Om den starkt skrivna komponenten endast innehåller ett element,
Om elementet redan har markerats som slutfört hoppar du över det.
Om elementet är ett argument lägger du till typtips från argumentet till de metodtypsparametrar som är beroende av det och markerar elementet som slutfört. Om argumentet är en lambda-metod med parametrar som fortfarande behöver härledda typer, härleder du
Objectför typerna av dessa parametrar.Om elementet är en metodtypsparameter kan du dra slutsatsen att parametern för metodtyp är den dominerande typen bland argumenttypens tips och markerar elementet som slutfört. Om ett typtips har en begränsning av matriselementet beaktas endast konverteringar som är giltiga mellan matriser av den angivna typen (dvs. covariant- och inbyggda matriskonverteringar). Om ett typtips har en allmän argumentbegränsning på sig beaktas endast identitetskonverteringar. Om ingen dominerande typ kan väljas misslyckas slutsatsdragningen. Om några lambda-metodargumenttyper är beroende av den här metodtypsparametern sprids typen till lambda-metoden.
Om den starkt inskrivna komponenten innehåller mer än ett element innehåller komponenten en cykel.
För varje metodtypparameter som är ett element i komponenten, om parametern för metodtyp är beroende av ett argument som inte är markerat som fullständigt, konverterar du det beroendet till ett påstående som ska kontrolleras i slutet av slutsatsdragningsprocessen.
Starta om slutsatsdragningsprocessen vid den tidpunkt då de starkt maskinskrivna komponenterna fastställdes.
Om typinferensen lyckas för alla metodtypsparametrar kontrolleras eventuella beroenden som har ändrats till kontroller. En försäkran lyckas om typen av argumentet implicit kan konverteras till den härledda typen av metodtypparameter. Om ett påstående misslyckas kan du skriva argumentinferens.
Med tanke på en argumenttyp Ta för ett argument A och en parametertyp Tp för en parameter Pgenereras typtips på följande sätt:
Om
Tpinte innehåller några metodtypsparametrar genereras inga tips.Om
TpochTaär matristyper med samma rangordning ersätterTadu ochTpmed elementtypernaTaför ochTpstartar om den här processen med en begränsning för matriselement.Om
Tpär en metodtypparameter läggs den tillTasom ett typtips med den aktuella begränsningen, om någon.Om
Aär en lambda-metod ochTpär en konstruerad ombudstyp ellerSystem.Linq.Expressions.Expression(Of T), därTär en konstruerad delegattyp, ersätter du medTLochTpmedTDoch startar om processen utan begränsning för varje lambda-metodparametertypTLoch motsvarande delegatparametertypTDTa. ErsättTasedan med returtypen för lambda-metoden och:- om
Aär en vanlig lambda-metod ersätter duTpmed returtypen för ombudstypen; - if
Ais async lambda method and the return type of the delegate type has formTask(Of T)for someT, replaceTpwith thatT; - om
Aär en iterator lambda-metod och returtypen för ombudstypen har formulärIEnumerator(Of T)ellerIEnumerable(Of T)för vissaTersätter duTpmed denT. - Starta sedan om processen utan begränsning.
- om
Om
Aär en metodpekare ochTpär en konstruerad ombudstyp använder du parametertypernaTpför för att avgöra vilken metod som är mest tillämplig förTp. Om det finns en metod som är mest tillämplig ersätter duTamed returtypen för metoden ochTpmed returtypen för ombudstypen och startar om processen utan begränsning.Annars
Tpmåste vara en konstruerad typ. GivetTG, den allmänna typen avTp,Om
TaärTG, ärver frånTGeller implementerar typenTGexakt en gång, ersätterTaxTadu med ochTpmedTpxoch startar om processen med en allmän argumentbegränsning för varje matchande typargumentTaxfrånTaochTpxfrånTp.Annars misslyckas typinferensen för den generiska metoden.
Lyckad typinferens garanterar inte i sig att metoden är tillämplig.
Visual Basic language spec