Megosztás a következőn keresztül:


Csuples (Visual Basic)

A Visual Basic 2017-től kezdve a Visual Basic nyelv beépített támogatást nyújt a tupolokhoz, amelyek megkönnyítik a tupolok létrehozását és az elemek elérését. A tuple egy könnyű adatstruktúra, amely meghatározott számú és sorrendű értéket tartalmaz. A rekord példányosításakor meg kell határoznia az egyes értékek (vagy elemek) számát és adattípusát. Egy kettős (vagy páros) két elemet tartalmaz. Az első lehet érték Boolean , míg a második egy String. Mivel a kukák megkönnyítik több érték egyetlen objektumban való tárolását, gyakran egyszerű módszerként használják őket, hogy több értéket adjanak vissza egy metódusból.

Fontos

A tuple támogatáshoz szükséges a ValueTuple típus. Ha a .NET-keretrendszer 4.7 nincs telepítve, hozzá kell adnia a NuGet-csomagotSystem.ValueTuple, amely elérhető a NuGet-katalógusban. A csomag nélkül a következőhöz hasonló fordítási hibát kaphat: "Az előre definiált "ValueTuple(Of,,,)" típus nincs definiálva vagy importálva."

A tuple példányosítása és használata

A vesszővel tagolt értékeket zárójelbe foglalva példányosíthatja a tupel-t. Ezek az értékek ezután a tupel mezőivé válnak. A következő kód például egy triplát (vagy 3-rekordot) határoz meg úgy, hogy Date az első érték, String a második, és Boolean a harmadik.

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

Alapértelmezés szerint a n-tuple egyes mezőinek neve a karakterláncból Item és a mező egy-alapú pozíciójával együtt áll össze az n-tuple-ban. Ebben a hármas tuplában a Date mező Item1, a String mező Item2, és a Boolean mező Item3. Az alábbi példa az előző kódsorban példányosított tuple mezőinek értékeit jeleníti meg.

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

A Visual Basic-tuple mezői írhatók és olvashatók; miután példányosított egy tupplét, módosíthatja az értékeit. Az alábbi példa az előző példában létrehozott rekord három mezőjéből kettőt módosít, és megjeleníti az eredményt.

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

Névvel ellátott tuple példányosítása és használata

Ahelyett, hogy alapértelmezett neveket használ egy rekord mezőihez, létrehozhat egy elnevezett rekordot úgy, hogy saját neveket rendel a rekord elemeihez. A rekord mezői ezután a hozzárendelt nevek vagy az alapértelmezett neveik alapján érhetők el. Az alábbi példa ugyanazt a 3 elemből álló tömböt példányosítja, mint korábban, azzal a kivétellel, hogy kifejezetten az első mezőt EventDate, a másodikat Name, és a harmadikat IsHoliday nevezi meg. Ezután megjeleníti a mezőértékeket, módosítja őket, és ismét megjeleníti a mezőértékeket.

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

A rekordneveket egy változó, mező vagy paraméter típusdeklarációjának részeként is megadhatja:

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

vagy egy metódus visszatérési típusában.

Ez különösen akkor hasznos, ha a gyűjtemény inicializálója számára elemeket biztosít; a tupelnevek a gyűjtemény típusának deklarációjának részeként adhatók meg.

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

Kikövetkeztetett elemek nevei

A Visual Basic 15.3-tól kezdve a Visual Basic képes a tömbök elemei nevére következtetni; nem kell explicit módon hozzárendelnie őket. A kikövetkeztetett rekordnevek akkor hasznosak, ha változókészletből inicializál egy rekordot, és azt szeretné, hogy a rekordelem neve megegyezik a változó nevével.

Az alábbi példa létrehoz egy hármaselemet stateInfo, amely három, kifejezetten megnevezett elemet tartalmaz, state, stateName, és capital. Vegye figyelembe, hogy az elemek elnevezésekor a rekord inicializálási utasítása egyszerűen hozzárendeli az elnevezett elemeket az azonos nevű változók értékeihez.

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

Mivel az elemeknek és a változóknak ugyanaz a neve, a Visual Basic fordító a mezők neveiből következtethet, ahogy az alábbi példa is mutatja.

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

A kikövetkeztetett elemnevek engedélyezéséhez meg kell határoznia, hogy a Visual Basic-fordító melyik verzióját szeretné használni a Visual Basic projektfájlban (*.vbproj).

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

A verziószám a Visual Basic fordító 15.3-tól kezdődő bármely verziója lehet. Egy adott fordítóverzió kemény kódolása helyett a "Latest" értéket is megadhatja a rendszerére telepített Visual Basic fordító legújabb verziójával való fordítás értékeként LangVersion .

További információ: A Visual Basic nyelvi verziójának beállítása.

Bizonyos esetekben a Visual Basic fordító nem tudja kikövetkeztetni a rekordelem nevét a jelölt névből, és a rekordmezőre csak az alapértelmezett nevével lehet hivatkozni, például Item1: , Item2stb. Ezek a következők:

  • A jelölt neve megegyezik egy tuple tag nevével, például Item3, Rest vagy ToString.

  • A jelölt neve megduplikálva lesz a tuple-ban.

Ha a mezőnév-következtetés sikertelen, a Visual Basic nem hoz létre fordítóhibát, és a futtatáskor sem keletkezik kivétel. Ehelyett a többes mezőkre az előre definiált neveik alapján kell hivatkozni, mint például Item1 és Item2.

Tömbök és struktúrák

A Visual Basic tuple olyan értéktípus, amely a System.ValueTuple általános típusainak egyik példánya. Az előző példában definiált holiday tömb például a ValueTuple<T1,T2,T3> struktúra egy példánya. Úgy tervezték, hogy egy könnyűsúlyú tároló az adatok számára. Mivel a tuple célja, hogy megkönnyítse egy több adatelemet tartalmazó objektum létrehozását, nem rendelkezik néhány olyan funkcióval, amelyek egy egyéni struktúrában megtalálhatók lennének. Ezek közé tartoznak:

  • Egyéni tagok. Nem definiálhat saját tulajdonságokat, függvényeket vagy eseményeket egy tuple-hoz.

  • Érvényesítés. A mezőkhöz rendelt adatok nem érvényesíthetők.

  • Nem módosítható. A Visual Basic-tuplesek nem módosíthatók. Ezzel szemben a saját struktúra lehetővé teszi annak irányítását, hogy egy példány módosítható vagy nem módosítható-e.

Ha az egyéni tagok, a tulajdonság- és mezőérvényesítés, illetve a nem módosíthatóság fontos, a Visual Basic Structure utasítással definiálhat egyéni értéktípust.

A Visual Basic-tuple örökli a ValueTuple típus tagjait. A mezők mellett ezek a következő módszereket is tartalmazzák:

Metódus Leírás
Összehasonlítás Összehasonlítja a jelenlegi n-tupletet egy másik n-tuplettel, amely ugyanannyi elemet tartalmaz.
Egyenlő Meghatározza, hogy az aktuális tuple egyenlő-e egy másik tuple-lal vagy objektummal.
Hash-kód beszerzése Kiszámítja az aktuális példány kivonatkódját.
ToString (objektum sztringgé alakítása) Ennek a tuple-nek a sztringként való ábrázolását adja vissza, amely a formátumot (Item1, Item2...) veszi fel, ahol Item1 és Item2 a tuple mezőinek értékeit képviselik.

Emellett a ValueTuple típusok megvalósítanak IStructuralComparable és IStructuralEquatable interfészeket, amelyek lehetővé teszik egyéni összehasonlítók definiálását.

Hozzárendelés és csuples

A Visual Basic támogatja az azonos számú mezővel rendelkező rekordtípusok közötti hozzárendelést. A mezőtípusok konvertálhatók, ha az alábbiak egyike igaz:

  • A forrás és a célmező azonos típusú.

  • A forrástípus céltípusra való kibővítése vagy implicit átalakítása meg van határozva.

  • Option Strict On, és meghatározzák a forrástípus céltípusra való szűkített (vagy explicit) konverzióját. Ez az átalakítás kivételt okozhat, ha a forrásérték kívül esik a céltípus tartományán.

Más átalakítások nem tekinthetők hozzárendeléseknek. Nézzük meg, hogy milyen típusú hozzárendelések (assignments) engedélyezettek a tuple típusok között.

Vegye figyelembe az alábbi példákban használt változókat:

' 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")

Az első két változó unnamedanonymousnem tartalmaz szemantikai neveket a mezőkhöz. A mezőneveik alapértelmezés szerint a Item1 és a Item2. Az utolsó két változó szemantikai nameddifferentName mezőnevekkel rendelkezik. Vegye figyelembe, hogy ez a két tuppel különböző nevekkel rendelkezik a mezők esetében.

E tupplák mind a négye azonos számú mezővel rendelkezik (ezt nevezik mezők számának vagy aritynek), és ezeknek a mezőknek a típusai azonosak. Ezért mindegyik feladat működik.

' 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

Figyelje meg, hogy a tömbök neve nincs hozzárendelve. A mezők értékei a tuple mezőinek sorrendjét követve vannak hozzárendelve.

Végül vegyük észre, hogy a(z) named tuple-t hozzárendelhetjük a(z) conversion tuple-höz, annak ellenére, hogy a(z) named első mezője egy Integer, míg a(z) conversion első mezője egy Long. Ez a hozzárendelés sikeres, mert a Integer-ről egy Long-re történő átalakítás kiszélesítő átalakítás.

' 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)

A különböző számú mezővel rendelkező tuplék nem rendelhetők hozzá:

' 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

Típusok mint metódus visszatérési értékek

A metódusok csak egyetlen értéket adhatnak vissza. Gyakran előfordul, hogy több értéket szeretne visszaadni egy metódushívással. Ennek a korlátozásnak több módja is van:

  • Létrehozhat olyan egyéni osztályt vagy struktúrát, amelynek tulajdonságai vagy mezői a metódus által visszaadott értékeket jelölik. Ez egy nehézsúlyú megoldás; ehhez olyan egyéni típust kell definiálnia, amelynek egyetlen célja az értékek lekérése egy metódushívásból.

  • A metódusból egyetlen értéket ad vissza, a fennmaradó értékeket pedig a metódusra való hivatkozással adja vissza. Ez magában foglalja egy változó példányosításának többletterhelését, és azzal a kockázattal jár, hogy véletlenül felülírja a hivatkozással átadott változó értékét.

  • Használhat egy tömböt, amely könnyű megoldást kínál több visszatérési érték lekérésére.

A .NET TryParse metódusai például olyan Boolean értéket adnak vissza, amely jelzi, hogy az elemzési művelet sikeres volt-e. Az elemzési művelet eredménye egy, a metódusra hivatkozva átadott változóban lesz visszaadva. Általában egy elemzési metódusra(például az Integer.TryParse ) való hívás a következőhöz hasonlóan néz ki:

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

Az elemzési műveletből vissza tudunk adni egy tuplet, ha az Integer.TryParse metódus hívását a saját metódusunkba csomagoljuk. Az alábbi példában a NumericLibrary.ParseInteger meghívja az Integer.TryParse metódust, és egy kételemű elnevezett tuple-t ad vissza.

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

Ezután az alábbihoz hasonló kóddal hívhatja meg a metódust:

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-tuple-ök és tuple-ök a .NET keretrendszerben

A Visual Basic tuple a System.ValueTuple generikus típusok egyik példánya, amelyet a .NET-keretrendszer 4.7 vezettek be. A .NET-keretrendszer általános System.Tuple-osztályokat is tartalmaz. Ezek az osztályok azonban számos módon különböznek a Visual Basic-tuplestől és a System.ValueTuple általános típustól:

  • A Tuple-osztályok elemei olyan tulajdonságok, amelyek nevei Item1, Item2, és így tovább. A Visual Basic tupulusokban és a ValueTuple típusokban a tupuluselemek mezők.

  • Nem rendelhet hozzá értelmes neveket egy Tuple-példány vagy egy ValueTuple-példány elemeihez. A Visual Basic lehetővé teszi olyan nevek hozzárendelését, amelyek közlik a mezők jelentését.

  • A Tuple példányok tulajdonságai írásvédettek, a tuple-ok nem módosíthatók. A Visual Basic tuplákban és a ValueTuple-típusokban a tuple mezők írhatók és olvashatók, a tuplák módosíthatók.

  • Az általános Tuple-típusok referenciatípusok. Ezeknek a Tuple-típusoknak a használata objektumok kiosztását jelenti. A gyakori elérésű útvonalakon ez mérhető hatással lehet az alkalmazás teljesítményére. A Visual Basic tuplái és a ValueTuple-típusok értéktípusok.

Az TupleExtensions osztály kiterjesztési metódusai megkönnyítik a Visual Basic tuple-ök és a .NET Tuple objektumok közötti konvertálást. A ToTuple metódus .NET Tuple objektummá alakítja a Visual Basic rekordokat, a ToValueTuple metódus pedig a .NET Tuple objektumot Visual Basic rekordmá alakítja.

Az alábbi példa létrehoz egy rekordot, .NET Tuple objektummá alakítja át, és visszaalakít egy Visual Basic-rekordra. A példa ezután összehasonlítja ezt a tömböt az eredeti tömbbel, biztosítva, hogy egyenlők legyenek.

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

Lásd még