Delen via


Tuples (Visual Basic)

Vanaf Visual Basic 2017 biedt de Visual Basic-taal ingebouwde ondersteuning voor tuples die het maken van tuples en het openen van de elementen van tuples eenvoudiger maken. Een tuple is een lichtgewicht gegevensstructuur met een specifiek aantal en een bepaalde reeks waarden. Wanneer u de tuple instantiëren, definieert u het getal en het gegevenstype van elke waarde (of element). Een 2-tuple (of paar) heeft bijvoorbeeld twee elementen. De eerste kan een Boolean waarde zijn, terwijl de tweede een String. Omdat tuples het gemakkelijk maken om meerdere waarden in één object op te slaan, worden ze vaak gebruikt als een lichtgewicht manier om meerdere waarden uit een methode te retourneren.

Belangrijk

Voor tuple-ondersteuning is het ValueTuple type vereist. Als .NET Framework 4.7 niet is geïnstalleerd, moet u het NuGet-pakket System.ValueTupletoevoegen, dat beschikbaar is in de NuGet-galerie. Zonder dit pakket krijgt u mogelijk een compilatiefout die vergelijkbaar is met 'Vooraf gedefinieerd type 'ValueTuple(Of,,,)' is niet gedefinieerd of geïmporteerd.'

Instantiëren en gebruiken van een tuple

U instantieert een tuple door de door komma's gescheiden waarden tussen haakjes te sluiten. Elk van deze waarden wordt vervolgens een veld van de tuple. De volgende code definieert bijvoorbeeld een drievoudige waarde (of drie tuples) met een Date als eerste waarde, een String als tweede en een Boolean als derde.

Dim holiday = (#07/04/2017#, "Independence Day", True)

Standaard bestaat de naam van elk veld in een tuple uit de tekenreeks Item , samen met de positie op basis van één veld in de tuple. Voor deze 3-tuple is het Date veld , het String veld is Item2en het Boolean veld is Item3.Item1 In het volgende voorbeeld worden de waarden weergegeven van velden van de tuple die is geïnstantieerd in de vorige regel code

Console.WriteLine($"{holiday.Item1} is {holiday.Item2}" +
                  $"{If(holiday.Item3, ", a national holiday", String.Empty)}")
' Output: 7/4/2017 12:00:00 AM Is Independence Day, a national holiday

De velden van een Visual Basic-tuple zijn lezen/schrijven; Nadat u een tuple hebt geïnstantieerd, kunt u de waarden ervan wijzigen. In het volgende voorbeeld worden twee van de drie velden van de tuple gewijzigd die in het vorige voorbeeld is gemaakt en wordt het resultaat weergegeven.

holiday.Item1 = #01/01/2018#
holiday.Item2 = "New Year's Day"
Console.WriteLine($"{holiday.Item1} is {holiday.Item2}" +
                  $"{If(holiday.Item3, ", a national holiday", String.Empty)}")
' Output: 1/1/2018 12:00:00 AM Is New Year's Day, a national holiday

Instantiëren en gebruiken van een benoemde tuple

In plaats van standaardnamen te gebruiken voor de velden van een tuple, kunt u een benoemde tuple instantiëren door uw eigen namen toe te wijzen aan de elementen van de tuple. De velden van de tuple kunnen vervolgens worden geopend door hun toegewezen namen of door hun standaardnamen. In het volgende voorbeeld wordt dezelfde 3-tuple geïnstitueerde als eerder, behalve dat het expliciet het eerste veld EventDate, de tweede Nameen de derde IsHolidaynoemt. Vervolgens worden de veldwaarden weergegeven, gewijzigd en worden de veldwaarden opnieuw weergegeven.

Dim holiday = (EventDate:=#07/04/2017#, Name:="Independence Day", IsHoliday:=True)
Console.WriteLine($"{holiday.EventDate} Is {holiday.Name}" +
                  $"{If(holiday.IsHoliday, ", a national holiday", String.Empty)}")
holiday.Item1 = #01/01/2018#
holiday.Item2 = "New Year's Day"
Console.WriteLine($"{holiday.Item1} is {holiday.Item2}" +
                  $"{If(holiday.Item3, ", a national holiday", String.Empty)}")
' The example displays the following output:
'   7/4/2017 12:00:00 AM Is Independence Day, a national holiday
'   1/1/2018 12:00:00 AM Is New Year's Day, a national holiday

U kunt ook de tuplenamen opgeven als onderdeel van de typedeclaratie van een variabele, veld of parameter:

Dim holiday As (EventDate As Date, Name As String, IsHoliday As Boolean) =
    (#07/04/2017#, "Independence Day", True)
Console.WriteLine(holiday.Name)
' Output: Independence Day

of in het retourtype van een methode.

Dit is met name handig bij het verstrekken van tuples aan een initialisatiefunctie voor verzamelingen; de tuplenamen kunnen worden opgegeven als onderdeel van de typedeclaratie van de verzameling:

Dim events As New List(Of (EventDate As Date, Name As String, IsHoliday As Boolean)) From {
    (#07/04/2017#, "Independence Day", True),
    (#04/22/2017#, "Earth Day", False)
}
Console.WriteLine(events(1).IsHoliday)
' Output: False

Namen van uitgestelde tuple-elementen

Vanaf Visual Basic 15.3 kan Visual Basic de namen van tuple-elementen afleiden; u hoeft ze niet expliciet toe te wijzen. Uitgestelde tuple-namen zijn handig wanneer u een tuple initialiseert vanuit een set variabelen en u wilt dat de naam van het tuple-element hetzelfde is als de naam van de variabele.

In het volgende voorbeeld wordt een stateInfo tuple gemaakt die drie expliciet benoemde elementen bevat, statestateNameen capital. Houd er rekening mee dat bij het benoemen van de elementen de tuple-initialisatie-instructie simpelweg de benoemde elementen de waarden van de identieke benoemde variabelen toewijst.

Const state As String = "MI"
Const stateName As String = "Michigan"
Const capital As String = "Lansing"
Dim stateInfo = (state:=state, stateName:=stateName, capital:=capital)
Console.WriteLine($"{stateInfo.stateName}: 2-letter code: {stateInfo.state}, Capital {stateInfo.capital}")
' The example displays the following output:
'      Michigan: 2-letter code: MI, Capital Lansing

Omdat elementen en variabelen dezelfde naam hebben, kan de Visual Basic-compiler de namen van de velden afleiden, zoals in het volgende voorbeeld wordt weergegeven.

Const state As String = "MI"
Const stateName As String = "Michigan"
Const capital As String = "Lansing"
Dim stateInfo = (state, stateName, capital)
Console.WriteLine($"{stateInfo.stateName}: 2-letter code: {stateInfo.State}, Capital {stateInfo.capital}")
' The example displays the following output:
'      Michigan: 2-letter code: MI, Capital Lansing

Als u de namen van uitgestelde tuple-elementen wilt inschakelen, moet u de versie van de Visual Basic-compiler definiëren die moet worden gebruikt in het Visual Basic-project (*.vbproj)-bestand:

<PropertyGroup>
  <LangVersion>15.3</LangVersion>
</PropertyGroup>

Het versienummer kan elke versie van de Visual Basic-compiler zijn vanaf 15.3. In plaats van een specifieke compilerversie hard te coderen, kunt u ook 'Nieuwste' opgeven als de waarde van LangVersion het compileren met de meest recente versie van de Visual Basic-compiler die op uw systeem is geïnstalleerd.

Zie voor meer informatie de versie van de Visual Basic-taal instellen.

In sommige gevallen kan de Visual Basic-compiler de naam van het tuple-element niet afleiden uit de naam van de kandidaat en kan alleen naar het tuple-veld worden verwezen met de standaardnaam, zoals Item1, Item2, enzovoort. Dit zijn onder andere:

  • De naam van de kandidaat is hetzelfde als de naam van een tuple-lid, zoals Item3, Restof ToString.

  • De naam van de kandidaat wordt gedupliceerd in de tuple.

Wanneer deductie van veldnamen mislukt, genereert Visual Basic geen compilerfout en wordt er ook geen uitzondering gegenereerd tijdens runtime. In plaats daarvan moeten tuple-velden worden verwezen door de vooraf gedefinieerde namen, zoals Item1 en Item2.

Tuples versus structuren

Een Visual Basic-tuple is een waardetype dat een exemplaar is van een van de algemene typen System.ValueTuple . De holiday tuple die in het vorige voorbeeld is gedefinieerd, is bijvoorbeeld een exemplaar van de ValueTuple<T1,T2,T3> structuur. Het is ontworpen als een lichtgewicht container voor gegevens. Omdat de tuple erop is gericht om eenvoudig een object met meerdere gegevensitems te maken, ontbreken enkele van de functies die een aangepaste structuur kan hebben. Deze omvatten:

  • Aangepaste leden. U kunt uw eigen eigenschappen, methoden of gebeurtenissen voor een tuple niet definiëren.

  • Validatie. U kunt de gegevens die zijn toegewezen aan velden niet valideren.

  • Onveranderbaarheid. Visual Basic-tuples zijn veranderlijk. Met een aangepaste structuur kunt u daarentegen bepalen of een exemplaar onveranderbaar of onveranderbaar is.

Als aangepaste leden, eigenschaps- en veldvalidatie of onveranderbaarheid belangrijk zijn, moet u de instructie Visual Basic Structure gebruiken om een aangepast waardetype te definiëren.

Een Visual Basic-tuple neemt de leden van het type ValueTuple over. Naast de velden zijn dit de volgende methoden:

Wijze Description
Compareto Vergelijkt de huidige tuple met een andere tuple met hetzelfde aantal elementen.
Is gelijk aan Bepaalt of de huidige tuple gelijk is aan een andere tuple of een ander object.
GetHashCode Berekent de hashcode voor het huidige exemplaar.
ToString Retourneert de tekenreeksweergave van deze tuple, die de vorm (Item1, Item2...)heeft, waarbij Item1 de waarden van de velden van de tuple worden aangegeven.Item2

Daarnaast implementeren IStructuralComparable de ValueTuple-typen en IStructuralEquatable interfaces, waarmee u aangepaste vergelijkingen kunt definiëren.

Toewijzingen en tuples

Visual Basic ondersteunt toewijzing tussen tuple-typen met hetzelfde aantal velden. De veldtypen kunnen worden geconverteerd als een van de volgende waar is:

  • Het bron- en doelveld hebben hetzelfde type.

  • Er wordt een verbreidingsconversie (of impliciete) conversie van het brontype naar het doeltype gedefinieerd.

  • Option Strict is On, en een beperkte (of expliciete) conversie van het brontype naar het doeltype is gedefinieerd. Deze conversie kan een uitzondering genereren als de bronwaarde buiten het bereik van het doeltype valt.

Andere conversies worden niet in aanmerking genomen voor toewijzingen. Laten we eens kijken naar de soorten toewijzingen die zijn toegestaan tussen tuple-typen.

Houd rekening met deze variabelen die worden gebruikt in de volgende voorbeelden:

' The number and field types of all these tuples are compatible. 
' The only difference Is the field names being used.
Dim unnamed = (42, "The meaning of life")
Dim anonymous = (16, "a perfect square")
Dim named = (Answer:=42, Message:="The meaning of life")
Dim differentNamed = (SecretConstant:=42, Label:="The meaning of life")

De eerste twee variabelen unnamed en anonymous, hebben geen semantische namen voor de velden. Hun veldnamen zijn de standaardinstelling Item1 en Item2. De laatste twee variabelen named en differentName hebben semantische veldnamen. Deze twee tuples hebben verschillende namen voor de velden.

Alle vier deze tuples hebben hetzelfde aantal velden (aangeduid als 'arity') en de typen van deze velden zijn identiek. Daarom werken al deze toewijzingen:

' Assign named to unnamed.
named = unnamed

' Despite the assignment, named still has fields that can be referred to as 'answer' and 'message'.
Console.WriteLine($"{named.Answer}, {named.Message}")
' Output:  42, The meaning of life

' Assign unnamed to anonymous.
anonymous = unnamed
' Because of the assignment, the value of the elements of anonymous changed.
Console.WriteLine($"{anonymous.Item1}, {anonymous.Item2}")
' Output:   42, The meaning of life

' Assign one named tuple to the other.
named = differentNamed
' The field names are Not assigned. 'named' still has 'answer' and 'message' fields.
Console.WriteLine($"{named.Answer}, {named.Message}")
' Output:   42, The meaning of life

U ziet dat de namen van de tuples niet zijn toegewezen. De waarden van de velden worden toegewezen volgens de volgorde van de velden in de tuple.

Ten slotte ziet u dat we de named tuple aan de conversion tuple kunnen toewijzen, ook al is het eerste veld named een Integer, en het eerste veld conversion is een Long. Deze toewijzing slaagt omdat het converteren van een Integer naar een Long een een breder wordende conversie is.

' Assign an (Integer, String) tuple to a (Long, String) tuple (using implicit conversion).
Dim conversion As (Long, String) = named
Console.WriteLine($"{conversion.Item1} ({conversion.Item1.GetType().Name}), " +
                  $"{conversion.Item2} ({conversion.Item2.GetType().Name})")
' Output:      42 (Int64), The meaning of life (String)

Tuples met verschillende aantallen velden kunnen niet worden toegewezen:

' Does not compile.
' VB30311: Value of type '(Integer, Integer, Integer)' cannot be converted
'          to '(Answer As Integer, Message As String)'
var differentShape = (1, 2, 3)
named = differentShape

Tuples als methode retourwaarden

Een methode kan slechts één waarde retourneren. Vaak wilt u echter dat een methode-aanroep meerdere waarden retourneert. Er zijn verschillende manieren om deze beperking te omzeilen:

  • U kunt een aangepaste klasse of structuur maken waarvan de eigenschappen of velden waarden vertegenwoordigen die door de methode worden geretourneerd. Dit is een zwaargewicht oplossing; Hiervoor moet u een aangepast type definiëren waarvan het enige doel is om waarden op te halen uit een methode-aanroep.

  • U kunt één waarde uit de methode retourneren en de resterende waarden retourneren door ze door te geven aan de methode. Dit omvat de overhead van het instantiëren van een variabele en risico's per ongeluk het overschrijven van de waarde van de variabele die u per verwijzing doorgeeft.

  • U kunt een tuple gebruiken, die een lichtgewicht oplossing biedt voor het ophalen van meerdere retourwaarden.

De TryParse-methoden in .NET retourneren bijvoorbeeld een Boolean waarde die aangeeft of de parseringsbewerking is geslaagd. Het resultaat van de parseringsbewerking wordt geretourneerd in een variabele die wordt doorgegeven door verwijzing naar de methode. Normaal gesproken ziet een aanroep naar een parseermethode er als Int32.TryParse volgt uit:

Dim numericString As String = "123456"
Dim number As Integer
Dim result = Integer.TryParse(numericString, number)
Console.WriteLine($"{If(result, $"Success: {number:N0}", "Failure")}")
'      Output: Success: 123,456

We kunnen een tuple retourneren uit de parseringsbewerking als we de aanroep naar de Int32.TryParse methode in onze eigen methode verpakken. In het volgende voorbeeld NumericLibrary.ParseInteger wordt de Int32.TryParse methode aangeroepen en wordt een benoemde tuple met twee elementen geretourneerd.

Imports System.Globalization

Public Module NumericLibrary
    Public Function ParseInteger(value As String) As (Success As Boolean, Number As Integer)
        Dim number As Integer
        Return (Integer.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, number), number)
    End Function
End Module

Vervolgens kunt u de methode aanroepen met code als de volgende:

Dim numericString As String = "123,456"
Dim result = ParseInteger(numericString)
Console.WriteLine($"{If(result.Success, $"Success: {result.Number:N0}", "Failure")}")
Console.ReadLine()
'      Output: Success: 123,456

Visual Basic-tuples en tuples in .NET Framework

Een Visual Basic-tuple is een exemplaar van een van de algemene typen System.ValueTuple , die zijn geïntroduceerd in .NET Framework 4.7. Het .NET Framework bevat ook een set algemene System.Tuple-klassen . Deze klassen verschillen echter op verschillende manieren van Visual Basic-tuples en de algemene typen System.ValueTuple :

  • De elementen van de Tuple-klassen zijn eigenschappen met de naam Item1, Item2enzovoort. In Visual Basic-tuples en de typen ValueTuple zijn tuple-elementen velden.

  • U kunt geen betekenisvolle namen toewijzen aan de elementen van een Tuple-exemplaar of van een ValueTuple-instantie . Met Visual Basic kunt u namen toewijzen die de betekenis van de velden communiceren.

  • De eigenschappen van een Tuple-exemplaar zijn alleen-lezen; de tuples zijn onveranderbaar. In Visual Basic-tuples en de typen ValueTuple zijn tuple-velden lezen/schrijven; de tuples kunnen worden gedempt.

  • De algemene Tuple-typen zijn referentietypen. Het gebruik van deze Tuple-typen betekent het toewijzen van objecten. Bij dynamische paden kan dit een meetbare invloed hebben op de prestaties van uw toepassing. Visual Basic-tuples en de typen ValueTuple zijn waardetypen.

Met extensiemethoden in de TupleExtensions klasse kunt u eenvoudig converteren tussen Visual Basic-tuples en .NET Tuple-objecten . Met de methode ToTuple wordt een Visual Basic-tuple geconverteerd naar een .NET Tuple-object en met de methode ToValueTuple wordt een .NET Tuple-object geconverteerd naar een Visual Basic-tuple.

In het volgende voorbeeld wordt een tuple gemaakt, geconverteerd naar een .NET Tuple-object en teruggezet naar een Visual Basic-tuple. In het voorbeeld wordt deze tuple vervolgens vergeleken met de oorspronkelijke tuple om ervoor te zorgen dat ze gelijk zijn.

Dim cityInfo = (name:="New York", area:=468.5, population:=8_550_405)
Console.WriteLine($"{cityInfo}, type {cityInfo.GetType().Name}")

' Convert the Visual Basic tuple to a .NET tuple.
Dim cityInfoT = TupleExtensions.ToTuple(cityInfo)
Console.WriteLine($"{cityInfoT}, type {cityInfoT.GetType().Name}")

' Convert the .NET tuple back to a Visual Basic tuple and ensure they are the same.
Dim cityInfo2 = TupleExtensions.ToValueTuple(cityInfoT)
Console.WriteLine($"{cityInfo2}, type {cityInfo2.GetType().Name}")
Console.WriteLine($"{NameOf(cityInfo)} = {NameOf(cityInfo2)}: {cityInfo.Equals(cityInfo2)}")

' The example displays the following output:
'       (New York, 468.5, 8550405), type ValueTuple`3
'       (New York, 468.5, 8550405), type Tuple`3
'       (New York, 468.5, 8550405), type ValueTuple`3
'       cityInfo = cityInfo2 :  True

Zie ook