C# Features

Last Updated: 12/2/2023

Tuples

  • tuples provides concise syntax to group multiple data elements in a lightweight data structure.
  • tuples, which are backed by System.ValueTuple are value types.
  • Data members of System.ValueTuple types are fields.
  • You can define tuples with an arbitrary large number of elements:

Simple

var person = ("siva", 30);
Console.WriteLine(person.Item1);
Console.WriteLine(person.Item2);

Specifying Data Types

(string, int) person = ("siva", 30);
Console.WriteLine(person.Item1);
Console.WriteLine(person.Item2);

Using Field Names

On Left Side

(string name, int age) person = ("siva", 30);
Console.WriteLine(person.name);
Console.WriteLine(person.age);

On Right Side

var person = (Name: "siva", Age: 30);
Console.WriteLine(person.Name);
Console.WriteLine(person.Age);

Using Variables

var name = "siva";
var age = 30;
var person = (name, age);
Console.WriteLine(person.name);
Console.WriteLine(person.age);

Using Classes

var person1 = new ValueTuple<string, int>("siva", 30);
var person2 = ValueTuple.Create<string, int>("ganesh", 20);

Usage

Tuples are commonly used in four ways:

  • To represent a single set of data. For example, a tuple can represent a database record, and its components can represent individual fields of the record.
  • To provide easy access to, and manipulation of, a data set.
  • To return multiple values from a method without using out parameters (in C#) or ByRef parameters (in Visual Basic).
  • To pass multiple values to a method through a single parameter.

Method Parameter

public static void DisplayPerson((string Name, int Age) person)
{
	Console.WriteLine($"{person.Name} is {person.Age} years old");
}
DisplayPerson(("siva", 30));

Method Return Type

Only Type

public static (string, int) GetPerson()
{
	return ("siva", 30);
}
var person = GetPerson();
Console.WriteLine(person.Item1);
Console.WriteLine(person.Item2);

With field names

public static (string name, int age) GetPerson()
{
	return ("siva", 30);
}
var person = GetPerson();
Console.WriteLine(person.name);
Console.WriteLine(person.age);

Deconstruction

  • C# features built-in support for deconstructing tuples, which lets you unpackage all the items in a tuple in a single operation.
(string name, int age) = GetPerson();
var (name, age) = GetPerson();
(var name, var age) = GetPerson();

Using existing variables

string name;
int age;
(name, age) = GetPerson();

Discard

  • You can discard as many values as you like; all are represented by the single discard, _.
(string name, _) = GetPerson();

Equality

  • Tuple assignment and tuple equality comparisons don't take field names into account.

Same names

var person1 = (name: "siva", age: 30);
var person2 = (name: "siva", age: 30);
Console.WriteLine(person1 == person2);  //true

Different names

var person1 = (name: "siva", age: 30);
var person2 = (fullName: "siva", age: 30);
Console.WriteLine(person1 == person2); //true

Different values

var person1 = (name: "siva", age: 30);
var person2 = (name: "kumar", age: 30);
Console.WriteLine(person1 == person2); //false

Assignment

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
(int, double) t1 = (17, 3.14); 
(double First, double Second) t2 = (0.0, 1.0); 
t2 = t1;

Alias

  • Beginning with C# 12, you can specify an alias for a tuple type with a using directive.
  • An alias doesn't introduce a new type, but only creates a synonym for an existing type.
// declare outside the class
using Point = (int X, int Y);

// use inside method
Point p1 = (10, 20)	;
Console.WriteLine(p1.X);
Console.WriteLine(p1.Y);

Limitations of The ValueTuple

  • Named-parameter feature of ValueTuples is just syntactic sugar to help with the readability and simplicity of our code.
  • Named parameters do not have a runtime representation, which means that under the hood, the C# compiler is going to revert the custom names we have given the elements to Item1, Item2, etc.
  • This has two main implications.
    • First, we cannot access our named parameters via reflection.
    • Secondly, if we cast a ValueTuple with named parameters to a dynamic type, trying to access the result elements using their custom names is going to give us a RuntimeBinderException because the system does not recognize those names anymore.

System.Tuple

  • System.Tuple types are reference types.
  • System.Tuple types are immutable.
  • Data members of System.Tuple types are properties.
  • You can create tuples of eight or more elements by nesting tuple objects in the Rest property of a Tuple<T1,T2,T3,T4,T5,T6,T7,TRest> object.
var person1 = new Tuple<string, int>("siva", 30);
var person2 = Tuple.Create<string, int>("siva", 30);

References: