Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Począwszy od Visual Basic 2017, język Visual Basic oferuje wbudowaną obsługę krotek, dzięki czemu tworzenie krotek i uzyskiwanie dostępu do ich elementów jest łatwiejsze. Krotka to lekka struktura danych, która ma określoną liczbę wartości i ich sekwencję. Instancjonując krotkę, należy zdefiniować liczbę i typ danych wartości (lub elementów). Na przykład 2-krotka (lub para) ma dwa elementy. Pierwsza może być wartością Boolean , a druga to String. Ponieważ krotki ułatwiają przechowywanie wielu wartości w jednym obiekcie, są one często używane jako uproszczony sposób zwracania wielu wartości z metody.
Ważne
Obsługa krotek wymaga typu ValueTuple. Jeśli program .NET Framework 4.7 nie jest zainstalowany, należy dodać pakiet System.ValueTupleNuGet, który jest dostępny w galerii NuGet. Bez tego pakietu może wystąpić błąd kompilacji podobny do "Wstępnie zdefiniowany typ "ValueTuple(Of,,,)" nie jest zdefiniowany lub zaimportowany.
Instancjowanie i używanie krotki
Aby utworzyć krotkę, umieść jej wartości oddzielone przecinkami w nawiasach. Każda z tych wartości staje się polem krotki. Na przykład poniższy kod definiuje trójkę (lub 3-krotkę) z wartością Date jako pierwszą, String jako drugą i Boolean jako trzecią.
Dim holiday = (#07/04/2017#, "Independence Day", True)
Domyślnie nazwa każdego pola w krotku składa się z ciągu Item wraz z jednokierunkową pozycją pola w krotku. W przypadku tej 3-krotki pole Date to Item1, pole String to Item2, a pole Boolean to Item3. Poniższy przykład przedstawia wartości pól krotki utworzonej w poprzednim wierszu kodu
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
Pola krotki w Visual Basic są do odczytu i zapisu; po utworzeniu wystąpienia krotki można zmodyfikować jej wartości. Poniższy przykład modyfikuje dwa z trzech pól krotki utworzonej w poprzednim przykładzie i wyświetla wynik.
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
Tworzenie wystąpienia i używanie nazwanego tuple’a
Zamiast używać nazw domyślnych dla pól krotki, można utworzyć wystąpienie nazwanej krotki , przypisując własne nazwy do elementów krotki. Następnie dostęp do pól krotki można uzyskać za pomocą przypisanych im nazw lub ich domyślnych nazw. Poniższy przykład tworzy wystąpienie tej samej 3-krotki co poprzednio, z tą różnicą, że jawnie nazywa pierwsze pole EventDate, drugie Name, i trzecie IsHoliday. Następnie wyświetla wartości pól, modyfikuje je i ponownie wyświetla wartości pól.
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
Nazwy krotek można również określić jako część deklaracji typu zmiennej, pola lub parametru:
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
lub w zwracanym typie metody.
Jest to szczególnie przydatne podczas dostarczania krotek do inicjatora kolekcji; nazwy krotek można podać w ramach deklaracji typu kolekcji.
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
Wywnioskowane nazwy elementów krotki
Począwszy od wersji Visual Basic 15.3, Visual Basic może samodzielnie wywnioskować nazwy elementów krotek; nie trzeba ich więc przypisywać jawnie. Wywnioskowane nazwy krotek są przydatne podczas inicjowania krotki z zestawu zmiennych, a nazwa elementu krotki ma być taka sama jak nazwa zmiennej.
Poniższy przykład tworzy krotkę zawierającą trzy jawnie nazwane elementy: stateInfo, state, stateName i capital. Należy pamiętać, że w nazewnictwie elementów instrukcja inicjowania krotki po prostu przypisuje nazwanym elementom wartości zmiennych o takich samych nazwach.
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
Ponieważ elementy i zmienne mają taką samą nazwę, kompilator języka Visual Basic może wywnioskować nazwy pól, jak pokazano w poniższym przykładzie.
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
Aby włączyć nazwy elementów krotki wnioskowanej, należy zdefiniować wersję kompilatora języka Visual Basic do użycia w pliku programu Visual Basic (*.vbproj):
<PropertyGroup>
<LangVersion>15.3</LangVersion>
</PropertyGroup>
Numer wersji może być dowolną wersją kompilatora Języka Visual Basic, począwszy od wersji 15.3. Zamiast ręcznie ustawiać konkretną wersję kompilatora, możesz również zadać "Latest" jako wartość LangVersion, aby kompilować z najnowszą wersją kompilatora Visual Basic zainstalowaną w systemie.
Aby uzyskać więcej informacji, zobacz ustawianie wersji języka Visual Basic.
W niektórych przypadkach kompilator języka Visual Basic nie może wywnioskować nazwy elementu krotki z nazwy kandydata, a do pola krotki można odwoływać się tylko przy użyciu jego nazwy domyślnej, takiej jak Item1, Item2 itp. Do takich przypadków należą:
Nazwa kandydata jest taka sama jak nazwa elementu członkowskiego krotki, na przykład
Item3,RestlubToString.Nazwa kandydata jest duplikowana w krotce.
Gdy wnioskowanie nazwy pola kończy się niepowodzeniem, visual Basic nie generuje błędu kompilatora ani nie zgłasza wyjątku w czasie wykonywania. Zamiast tego, do pól krotek należy odwoływać się za pomocą ich wstępnie zdefiniowanych nazw, takich jak Item1 i Item2.
Krotki kontra struktury
Krotka języka Visual Basic to typ wartości, który jest instancją jednego z typów ogólnych System.ValueTuple. Na przykład holiday krotka zdefiniowana w poprzednim przykładzie jest wystąpieniem ValueTuple<T1,T2,T3> struktury. Został zaprojektowany tak, aby był lekkim kontenerem danych. Ponieważ krotka ma na celu ułatwienie tworzenia obiektu z wieloma elementami danych, brakuje jej niektórych funkcji, które może mieć struktura dostosowana. Są to:
Niestandardowi członkowie. Nie można zdefiniować własnych właściwości, metod ani zdarzeń dla krotek.
Walidacja. Nie można zweryfikować danych przypisanych do pól.
Niezmienność. Krotki języka Visual Basic są modyfikowalne. Natomiast struktura niestandardowa umożliwia kontrolowanie, czy wystąpienie jest modyfikowalne, czy niezmienne.
Jeśli członkowie niestandardowi, walidacja właściwości i pola lub niezmienność są ważne, należy użyć instrukcji Visual Basic Structure do zdefiniowania niestandardowego typu wartości.
Krotka języka Visual Basic dziedziczy elementy członkowskie typu ValueTuple . Oprócz swoich pól, obejmują one następujące metody:
| Metoda | opis |
|---|---|
| CompareTo | Porównuje bieżącą krotkę z inną krotką o tej samej liczbie elementów. |
| Równa się | Określa, czy bieżąca krotka jest równa innej krotce lub obiektowi. |
| GenerujSkrót | Oblicza kod skrótu dla bieżącego wystąpienia. |
| ToString | Zwraca reprezentację ciągu tej krotki, która przyjmuje formę (Item1, Item2...), gdzie Item1 i Item2 reprezentują wartości pól krotki. |
Ponadto typy ValueTuple implementują interfejsy IStructuralComparable i IStructuralEquatable, co umożliwia definiowanie niestandardowych porównywarek.
Przypisania i krotki
Język Visual Basic obsługuje przypisywanie pomiędzy typami krotek, które mają identyczną liczbę pól. Typy pól można przekonwertować, jeśli jedna z następujących wartości ma wartość true:
Pole źródłowe i docelowe mają ten sam typ.
Zdefiniowano konwersję rozszerzającą (lub niejawną) typu źródłowego na typ docelowy.
Option StricttoOn, a zdefiniowana jest zawężająca (lub jawna) konwersja typu źródłowego na typ docelowy. Ta konwersja może zgłosić wyjątek, jeśli wartość źródłowa przekracza zakres typu docelowego.
Inne konwersje nie są brane pod uwagę w przypadku przypisań. Przyjrzyjmy się rodzajom przypisań dozwolonych między typami krotek.
Rozważ te zmienne używane w następujących przykładach:
' 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")
Pierwsze dwie zmienne unnamed i anonymous, nie mają nazw semantycznych podanych dla pól. Ich nazwy pól są domyślne Item1 i Item2. Dwie ostatnie zmienne named i differentName mają nazwy pól semantycznych. Należy pamiętać, że te dwie krotki mają różne nazwy pól.
Wszystkie cztery krotki mają taką samą liczbę pól (nazywanych "arity"), a typy tych pól są identyczne. W związku z tym wszystkie te przypisania działają:
' 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
Zwróć uwagę, że nazwy krotek nie są przypisane. Wartości pól są przypisywane zgodnie z kolejnością pól w krotce.
Na koniec zwróć uwagę, że możemy przypisać krotkę named do krotki conversion, mimo że pierwsze pole named jest Integer, a pierwsze pole conversion obiektu Long to Long. To przypisanie powiedzie się, ponieważ konwersja Integer na element Long jest konwersją rozszerzającą.
' 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)
Krotki z różnymi liczbami pól nie można przypisać:
' 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
Krotki jako wartości zwracane przez metodę
Metoda może zwracać tylko jedną wartość. Często jednak chcesz, aby wywołanie metody zwracało wiele wartości. Istnieje kilka sposobów obejścia tego ograniczenia:
Można utworzyć niestandardową klasę lub strukturę, której właściwości lub pola reprezentują wartości zwracane przez metodę. To rozwiązanie obciążające. Wymaga zdefiniowania typu niestandardowego, którego jedynym celem jest pobranie wartości z wywołania metody.
Możesz zwrócić pojedynczą wartość z metody, a pozostałe wartości przekazać przez odwołanie do tejże metody. Obejmuje to narzut związany z tworzeniem instancji zmiennej i ryzykiem nieumyślnego zastępowania wartości zmiennej przekazywanej przez referencję.
Możesz użyć krotki, która zapewnia lekkie rozwiązanie do pobierania wielu wartości zwracanych.
Na przykład metody TryParse w .NET zwracają wartość Boolean, która wskazuje, czy operacja analizowania zakończyła się pomyślnie. Wynik operacji analizowania jest zwracany w zmiennej przekazanej przez odwołanie do metody. Zwykle wywołanie metody analizowania, takiej jak Integer.TryParse , wygląda następująco:
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
Możemy zwrócić krotkę z operacji parsowania, jeśli owiniemy wywołanie metody Integer.TryParse we własnej metodzie. W poniższym przykładzie NumericLibrary.ParseInteger wywołuje metodę Integer.TryParse i zwraca nazwaną krotkę z dwoma elementami.
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
Następnie można wywołać metodę za pomocą kodu, takiego jak:
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
Krotki i krotki języka Visual Basic w programie .NET Framework
Krotka języka Visual Basic jest wystąpieniem jednego z typów ogólnych System.ValueTuple , które zostały wprowadzone w programie .NET Framework 4.7. Program .NET Framework zawiera również zestaw ogólnych klas System.Tuple . Te klasy różnią się jednak od krotek języka Visual Basic i typów ogólnych System.ValueTuple pod wieloma względami:
Elementy klas Tuple są właściwościami o nazwie
Item1,Item2, itd. W krotkach języka Visual Basic i typach ValueTuple elementy krotki są polami.Nie można przypisać znaczących nazw do elementów wystąpienia krotki ani ValueTuple. Visual Basic umożliwia przypisywanie nazw, które komunikują znaczenie pól.
Właściwości wystąpienia krotki są tylko do odczytu; krotki są niezmienne. W krotkach i typach ValueTuple w języku Visual Basic pola krotek są do odczytu i zapisu; krotki są modyfikowalne.
Typy ogólne Tuple są typami referencyjnymi. Używanie tych typów krotek wiąże się z alokacją obiektów. W przypadku ścieżek gorących może to mieć wymierny wpływ na wydajność aplikacji. Krotki języka Visual Basic i typy ValueTuple są typami wartości.
Metody rozszerzeń w TupleExtensions klasie ułatwiają konwertowanie między krotkami Visual Basic a obiektami .NET Tuple. Metoda ToTuple konwertuje krotkę języka Visual Basic na obiekt Tuple .NET, a metoda ToValueTuple konwertuje obiekt .NET Tuple na krotkę języka Visual Basic.
Poniższy przykład tworzy krotkę, konwertuje ją na obiekt Tuple platformy .NET i konwertuje ją z powrotem na krotkę w języku Visual Basic. W tym przykładzie porównano tę krotkę z oryginalną, aby upewnić się, że są one równe.
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