Tuple c что это
Кортежи предоставляют удобный способ для работы с набором значений, который был добавлен в версии C# 7.0.
Кортеж представляет набор значений, заключенных в круглые скобки:
В данном случае определен кортеж tuple, который имеет два значения: 5 и 10. В дальнейшем мы можем обращаться к каждому из этих значений через поля с названиями:
В данном случае тип определяется неявно. Но мы также можем явным образом указать для переменной кортежа тип:
Так как кортеж содержит два числа, то в определении типа нам надо указать два числовых типа. Или другой пример определения кортежа:
Первый элемент кортежа в данном случае представляет строку, второй элемент — тип int, а третий — тип double.
Мы также можем дать названия полям кортежа:
Теперь чтобы обратиться к полям кортежа используются их имена, а не названия Item1 и Item2.
Мы даже можем выполнить декомпозицию кортежа на отдельные переменные:
Одной из задач, которую позволяет элегантно решить кортеж — это обмен значениями:
Что можно использовать, например, при простейшей сортировке массива:
Кортеж как результат метода
Кортежи могут выступать в качестве результата функции. Например, одной из распространенных ситуаций является возвращение из функции двух и более значений, в то время как функция может возвращать только одно значение. И кортежи представляют оптимальный способ для решения этой задачи:
Здесь определен метод GetValues() , который возвращает кортеж. Кортеж определяется как набор значений, помещенных в круглые скобки. И в данном случае мы возвращаем кортеж из двух элементов типа int, то есть два числа.
Кортеж как параметр метода
И также кортеж может передаваться в качестве параметра в метод:
Здесь в метод PrintPerson передается кортеж из двух элементов, первый из которых предоставляет строку, а второй — значение типа int.
Кортежи (tuple) в C#
Кортежи появились в C# начиная с версии 7.0 с целью обеспечения работы с наборами значений. Основное предназначение кортежей — обобщение нескольких элементов в структуру с упрощенным синтаксисом. Для использования кортежей необходим тип System.ValueTuple. Для использования кортежей в более ранних версиях .NET Framework в проект необходимо добавить NuGet пакет SystemValueTuple.
Основные свойства кортежей:
кортежи определяются с неограниченным количеством элементов.
Кортежи являются типом значений.
Кортежи поддерживают операторы = и !=
Значения кортежей являются общедоступными полями.
Обращение к значениям кортежа происходит через поля с названиями типа Item[номер], где номер — порядковый номер значения в кортеже. Рассмотрим на примере программы:
Возможно определение типа для каждого из значений. Для этого перед именем кортежа в скобках указываются типы для каждого значения.
Для каждого значения кортежа предусмотрена возможность индивидуального именования. Заданное имя элемента называется именем кандидата. Оно является дубликатором другого явного или неявного имени поля кортежа.
Для определения кортежей можно применять переменные, с которыми в дальнейшем можно производить операции.
Применение кортежей
Кортежи могут передаваться в метод в качестве параметров и служить возвращаемым результатом. В частности, очень удобно возвращать кортеж в качестве результата в том случае, если метод возвращает только одно значение.
В следующем примере кортеж передается в метод в качестве параметра.
Присваивание кортежей
В кортежах предусмотрена возможность присваивания. Для этого оба кортежа должны иметь одинаковое количество элементов, типы соответствующих значений должны совпадать или иметь возможность неявного приведения друг к другу. Значения присваиваются в порядке их расположения. При присвоении имена полей не учитываются.
Деконструкция кортежей
Деконструкцией кортежей называется операция присваивания экземпляра кортежа в отдельные переменные.
Проверка кортежей на равенство
Имена полей кортежей при сравнении не учитываются.
Условия возможности сравнения кортежей:
Оба кортежа содержат одинаковое количество элементов.
Элементы должны соответствовать возможности сравнения.
Кортежи в качестве параметров вывода
При выполнении рефакторинга метода, имеющего параметры out они могут иметь тип кортежа.
Различия между типами кортежей System.ValueTuple и SystemTuple
Основные различия заключаются в следующем:
Типы ValueTuple являются типами значений — типы Tuple — ссылочные типы.
Типы ValueTuple являются изменяемыми типами — типы Tuple — неизменяемые.
Значениями типов ValueTuple являются поля. Значениями типов Tuple являются свойства.
C# Tuple – How to use Tuples in C#
A tuple is a lightweight data structure that provides concise syntax to group multiple data elements. In this article, I will show you how to work with a C# tuple.
Ever been in need to pass multiple values around at the same time? By using a C# Tuple we can do just that – but with a little warning. Tuples can be hard to understand and use. When I first started using Tuples I asked myself: how are the values inside a tuple related? How can we place our data in a tuple into variables in the code that has meaningful names?
If you like me, create software and need a quick way to move data around, this guide will help you to do that by teaching you how to add tuples to your own project the right way.
If you are ready to get started with C# tuples and learn to get them working under the hood of your application, then let’s move on.
Is C# Tuple the same as System.Tuple?
When I started using tuples, I got confused by the two. A C# tuple is not the same as System.Tuple . System.Tuple makes use of a class and a C# tuple is backed by System.ValueTuple.
As I just mention, System.Tuple are classes, where System.ValueTuple are structs. The great thing about using a ValueTuple is that it is mutable and not “read-only” like a System.Tuple is. The members of System.ValueTuple are fields, where System.Tuple are properties (because of the class).
If you are using C# 7 or later, I would recommend you to use System.ValueTuple . If you are using an older version, then you are forced to use System.Tuple . I will show you how to use both of them in this article – don’t worry.
When to use a Tuple?
A tuple is perfect for moving data around in your application, without having to create a new model/class to hold your data.
The most common cases where I use tuples are:
– When I need to group related values.
– When I have to return multiple values from a function without using the out parameter.
– When I do LINQ projection. (When I need to extract a subset of elements from a sequence of data).
What is a Tuple in C#?
Tuple initially appeared in .NET framework 4.0 and it can contain up to seven elements plus one optional TRest property as the eighth element – (Tuple<T1,T2,T3,T4,T5,T6,T7,TRest>) . The TRest property is mostly for extension purposes and can hold a nested tuple object.
Tuple should not be mistaken for ValueTuple , which has been introduced as an improvement in C#7. We’re going to talk about the differences a bit later on.
Using System.Tuple
System.Tuple is a tuple implementation that makes use of classes. This was the defacto standard prior to C# 7 – which is the reason why it’s widely used in many “old” applications. Lots of developers still use it.
Type arguments with System.Tuple
The old tuple classes require type arguments. When you create new tuples you must provide them using the new constructor. The number and types of tuple members are determined på the type arguments, hence they are important.
Below is an example of a tuple with two members of string type:
If you create a new tuple without specifying the type of arguments in the constructor, your compiler will return an error. Here is an example:
Tuple.Create() – Why not just use new?
When working with System.Tuple , we got two options for creating tuples. Tuple.Create() and new Tuple() . So what is the difference? There is no difference… I prefer to use Tuple.Create() because I find it more concise and it makes my code easier to read for other developers including myself in the future when I have to come back and refactor something.
The core difference between the two is that you don’t have to specify your argument types when using Tuple.Create() . As I mentioned earlier, you will get a compiler error, if you don’t specify the argument types when using the new constructor.
If you take a look at the code behind it, you will see that both ways actually do the same thing. When you use Tuple.Create() it will call the Tuple() constructor with a set of default values.
Below is an example of how the two of them are doing the same job using generic arguments.
How to access data in System.Tuple?
When you create a new tuple and want to access the data inside it (your values) you only have to specify the item you would like the value for. Elements in System.Tuple does not make use of names, instead, you have to use an ordinal index to access the values in your tuple.
How to update the value of a System.Tuple member?
It’s easy – you cant. System.Tuple is immutable. Once it’s created, you cannot change it. If you try to do it, you will end up with a compiler error.
If you need to update the value, you would have to destroy and re-create the tuple with the new value you would like to have in the tuple:
Using C# Tuple (System.ValueTuple) – Since C# 7
Tuple in C# is a reference-type data structure that allows the storage of items of different data types. It comes in handy when we need to create an object that can hold items of different data types but we don’t want to create a completely new type.
My favorite and the one I always use if possible. The C# Tuple is a comma-separated list of values enclosed in parentheses. With this type, we can have nested tuples + values counting from 0 to many.
A C# tuple since C# 7 has the following syntax.
How to declare a C# Tuple?
I always use names when specifying my tuples, to make the code easier to read and maintain. The ultimate easier method is just by using the parentheses syntax though.
In the example above you can see both ways to declare the tuples.
How to update a C# tuple value?
Opposite of System.Tuple , a C# tuple is mutable. The developers behind C# changed the new kind of tuples to be implemented as a ValueTuple which is a struct, that we are able to update.
It is very easy to update a tuple at runtime. We only have to specify the new value for the element in the tuple. An example is shown below of how you can accomplish that task.
How to use Named Tuples
By default, each member of your tuple is constructed with a name like “item1”, “item2”, “item3”, etc… Whenever I see someone do that in C# 7 or later, I decline the pull request with a comment telling them to update the tuple with the naming of the members because it is harder to read the code for other developers resulting in a codebase that’s harder to maintain in the future. PLEASE use named tuples whenever possible!
Since C# 7 a new type of tuple has been introduced – “named tuple”. A named tuple can have named members – which makes the code easier to write and maintain.
Below is an example of how to create a named tuple based on the example above with coordinates.
How to do tuple deconstruction?
Ever wondered how you could extract the value of a named tuple by creating a method? Tuple deconstruction is a nice feature that allows us to extract values from a tuple into separate variables.
C# got a special syntax we can use to deconstruct a C# tuple to get the value of the members. To deconstruct a C# tuple, you actually just have to use the same syntax as when you initially created the C# tuple.
Below is an example of how you can extract the city name from a tuple, with this format: (string, string, int, string). The only thing you have to do is call the method GetCity and pass the tuple to it:
The underscore(s) “_” is present because we would like to ignore the other values. We only want value number two (index 1) – the city from the C# tuple.
Tuple vs Enum and Dictionary
A tuple is very often used instead of an enum since enums in C# don’t support string values. I have made an example below to show you what I mean:
If we told our compiler to build this you would get a compiler error. The reason is that enums only support numeric values, hence tuples are a good idea to use. This would be a solution:
If you normally would you a dictionary, I would advise you to switch to C# tuples as they often are more concise.
You might be thinking – are they not quite the same? In some way. A dictionary like this: Dictionary<TKey, TValue> is a way to structure data into key-value pairs. You are able to store any type and any value you would like. The only problem is that you can only store one value per key. If you were using tuples, you would be able to store multiple values using the same key.
That’s why I often use a C# tuple instead of a dictionary.
Summary
In this article, we have taken a look at both types of tuples in the .NET ecosystem. A c# tuple is a great way to parse and return multiple values to/from a method without having to create a new model. Tuples can be difficult to understand, so please use them with caution.
Tuples should not be used in all cases. I got a rule of thumb that goes like this: If I got less than three items I will use a tuple to move data around. If you got more items, please create a class as they are easier to maintain and add a standard for that specific type of data.
I hope you learned some new programming techniques from this article. If you got any issues, questions, or suggestions, please let me know in the comments. Happy coding!
Name already in use
docs / docs / csharp / language-reference / builtin-types / value-tuples.md
- Go to file T
- Go to line L
- Copy path
- Copy permalink
- Open with Desktop
- View raw
- Copy raw contents Copy raw contents
Copy raw contents
Copy raw contents
Tuple types (C# reference)
The tuples feature provides concise syntax to group multiple data elements in a lightweight data structure. The following example shows how you can declare a tuple variable, initialize it, and access its data members:
As the preceding example shows, to define a tuple type, you specify types of all its data members and, optionally, the field names. You cannot define methods in a tuple type, but you can use the methods provided by .NET, as the following example shows:
Tuple types support equality operators == and != . For more information, see the Tuple equality section.
Tuple types are value types; tuple elements are public fields. That makes tuples mutable value types.
[!NOTE] The tuples feature requires the xref:System.ValueTuple?displayProperty=nameWithType type and related generic types (for example, xref:System.ValueTuple%602?displayProperty=nameWithType), which are available in .NET Core and .NET Framework 4.7 and later. To use tuples in a project that targets .NET Framework 4.6.2 or earlier, add the NuGet package System.ValueTuple to the project.
You can define tuples with an arbitrary large number of elements:
Use cases of tuples
One of the most common use cases of tuples is as a method return type. That is, instead of defining out method parameters, you can group method results in a tuple return type, as the following example shows:
As the preceding example shows, you can work with the returned tuple instance directly or deconstruct it in separate variables.
You can also use tuple types instead of anonymous types; for example, in LINQ queries. For more information, see Choosing between anonymous and tuple types.
Typically, you use tuples to group loosely related data elements. That is usually useful within private and internal utility methods. In the case of public API, consider defining a class or a structure type.
Tuple field names
You can explicitly specify the names of tuple fields either in a tuple initialization expression or in the definition of a tuple type, as the following example shows:
If you don’t specify a field name, it may be inferred from the name of the corresponding variable in a tuple initialization expression, as the following example shows:
That’s known as tuple projection initializers. The name of a variable isn’t projected onto a tuple field name in the following cases:
- The candidate name is a member name of a tuple type, for example, Item3 , ToString , or Rest .
- The candidate name is a duplicate of another tuple field name, either explicit or implicit.
In those cases you either explicitly specify the name of a field or access a field by its default name.
The default names of tuple fields are Item1 , Item2 , Item3 and so on. You can always use the default name of a field, even when a field name is specified explicitly or inferred, as the following example shows:
At compile time, the compiler replaces non-default field names with the corresponding default names. As a result, explicitly specified or inferred field names aren’t available at run time.
[!TIP] Enable .NET code style rule IDE0037 to set a preference on inferred or explicit tuple field names.
Tuple assignment and deconstruction
C# supports assignment between tuple types that satisfy both of the following conditions:
- both tuple types have the same number of elements
- for each tuple position, the type of the right-hand tuple element is the same as or implicitly convertible to the type of the corresponding left-hand tuple element
Tuple element values are assigned following the order of tuple elements. The names of tuple fields are ignored and not assigned, as the following example shows:
You can also use the assignment operator = to deconstruct a tuple instance in separate variables. You can do that in one of the following ways:
Explicitly declare the type of each variable inside parentheses:
Use the var keyword outside the parentheses to declare implicitly typed variables and let the compiler infer their types:
Use existing variables:
For more information about deconstruction of tuples and other types, see Deconstructing tuples and other types.
Tuple types support the == and != operators. These operators compare members of the left-hand operand with the corresponding members of the right-hand operand following the order of tuple elements.
As the preceding example shows, the == and != operations don’t take into account tuple field names.
Two tuples are comparable when both of the following conditions are satisfied:
- Both tuples have the same number of elements. For example, t1 != t2 doesn’t compile if t1 and t2 have different numbers of elements.
- For each tuple position, the corresponding elements from the left-hand and right-hand tuple operands are comparable with the == and != operators. For example, (1, (2, 3)) == ((1, 2), 3) doesn’t compile because 1 is not comparable with (1, 2) .
The == and != operators compare tuples in short-circuiting way. That is, an operation stops as soon as it meets a pair of non equal elements or reaches the ends of tuples. However, before any comparison, all tuple elements are evaluated, as the following example shows:
Tuples as out parameters
Typically, you refactor a method that has out parameters into a method that returns a tuple. However, there are cases in which an out parameter can be of a tuple type. The following example shows how to work with tuples as out parameters: