Many a times we would like to return more than one values from a method call. C# provided lot of features to support this functionality. Some of them are:
- Out Parameter
- Ref Parameter
- Anonymous types can be returned via dynamic keywords
- Tuples
C# 4.0 introduced a type Tuple<…> using which you can return more than one value from a function without creating a new type. Tuple behaves like a dictionary with each returned item accessible as Item1, Item2 and so on. This is very verbose and require a Tuple object to be created.
Example using C# 4.0
Tuple<int, int> ReturnRuntimeTimeEncapsulatingTwoValues() { return new Tuple<int, int>(1, 2); } private void btnTuple6_Click(object sender, EventArgs e) { Tuple<int, int> tuple = ReturnRuntimeTimeEncapsulatingTwoValues(); //Usage in c# 6 int value1 = tuple.Item1; //No control over member name and its too unintuitive int value2 = tuple.Item2; }
style="display:block; text-align:center;"
data-ad-format="fluid"
data-ad-layout="in-article"
data-ad-client="ca-pub-5021110436373536"
data-ad-slot="9215486331">
As you can see we created a method ReturnRuntimeTimeEncapsulatingTwoValues which returns 2 integer values wrapped inside a Tuple object. Values are further accessed by caller as Item1 and Item2.
C# 7.0 introduces the concept of Tuple Types and Tuple Literals with lot of support for de-structuring Tuples into local variable on the fly without need for creating Tuple objects
(int x, int y) ReturnRuntimeTimeEncapsulatingTwoValuesCSharp7Style() { return (1, 2); } private void btnCsharp7_Click(object sender, EventArgs e) { (int x, int y) tuple = ReturnRuntimeTimeEncapsulatingTwoValuesCSharp7Style(); //Usage in c# 7 int value1 = tuple.x; //Full control over member name and its too intuitive int value2 = tuple.y; //Another way to define tuple (int x, int y) anotherTuple = (x: 20, y: 12); //Named parameter syntax //Unfortunately this is not allowed (int x, int y) anotherTupleWithDifferentOrder = (y: 20, x: 12); //Named parameter syntax //Direct depackaging or deconstruction (int x, int y) = ReturnRuntimeTimeEncapsulatingTwoValuesCSharp7Style(); int newX = x; int newY = y; //Custom Depacking for types var complexNumber = new ComplexNumber(2, 3); (float real, float imaginary) = complexNumber; float realValue = real; float imaginaryValue = imaginary; }
As you can see we created a method ReturnRuntimeTimeEncapsulatingTwoValues which returns 2 integer values wrapped inside a Tuple object.
There are various ways you can utilize the values in C# 7.0
style="display:block; text-align:center;"
data-ad-format="fluid"
data-ad-layout="in-article"
data-ad-client="ca-pub-5021110436373536"
data-ad-slot="9215486331">
- Wrapping them inside a Tuple object i.e. tuple and accessing using tuple.x and tuple.y
(int x, int y) tuple = ReturnRuntimeTimeEncapsulatingTwoValuesCSharp7Style(); //Usage in c# 7 int value1 = tuple.x; //Full control over member name and its too intuitive int value2 = tuple.y;
- Directly de-structuring returned value to local variables x and y as
//Direct depackaging or deconstruction
(int x, int y) = ReturnRuntimeTimeEncapsulatingTwoValuesCSharp7Style(); Console.WriteLine(x); Console.WriteLine(y);
- Using Named parameter syntax
(int x, int y) anotherTuple = (x: 20, y: 12); //Named parameter syntax //Unfortunately this is not allowed (int x, int y) anotherTupleWithDifferentOrder = (y: 20, x: 12); //Named parameter syntax
style="display:block; text-align:center;"
data-ad-format="fluid"
data-ad-layout="in-article"
data-ad-client="ca-pub-5021110436373536"
data-ad-slot="9215486331">
Creating de-structuring for custom types
For this demo, I have created a class Complex with real and imaginary variable as data members as follows
class ComplexNumber { float real; float imaginary; public ComplexNumber(float x , float y) { this.real = x; this.imaginary = y; } public System.Tuple<float, float> Deconstruction( float real, float imaginary) { return new System.Tuple<float, float>( this.real,this.imaginary); } }
Before C# 6.0 Values from Deconstruction method can be depackaged as
var complexNumber = new ComplexNumber(2, 3); Tuple<float, float> tupleValue = complexNumber.Deconstruction(); Console.WriteLine(tupleValue.Item1); Console.WriteLine(tupleValue.Item2);
Using C# 7.0 we can add a new de-structuring behavior to complex number class as below
class ComplexNumber { float real; float imaginary; public ComplexNumber(float x , float y) { this.real = x; this.imaginary = y; } public void Deconstruct(out float real, out float imaginary) { real = this.real; imaginary = this.imaginary; } }
And thus, usage can be simplified as
style="display:block; text-align:center;"
data-ad-format="fluid"
data-ad-layout="in-article"
data-ad-client="ca-pub-5021110436373536"
data-ad-slot="9215486331">
var complexNumber = new ComplexNumber(2, 3); (float real, float imaginary) = complexNumber; float realValue = real; float imaginaryValue = imaginary;
All code samples are available at my GitHub profile
I am a corporate trainer and solution architect and have a great team of software professionals. Please contact in case you need our services by sending email to contact@techprocompsoft.com. Here is our company website .