Tips in C#
This page is a reminder and how-to for my best tips in C#
How to return multiple parameters from functions: the tuples way
Often it's useful to return more than one parameter from a function.
In the following example we have to pass to caller two values: one string and one
int.
There are several solution to this problem applicable in C# language.
1) The function requests one or more input parameters with keyword out (or ref).
In this way the caller can receive a 'normal' return parameter and one or more out
parameters that contains the other values.
public string ReturnTwoParams(out int param2)
{
param2 = 10;
return "string value";
}
private void Test()
{
string param1;
int param2;
param1 = ReturnTwoParams(out param2);
}
|
This is a vintage method difficult to read and not elegant. In other words a so
called 'gemyan' practice.
2) The return parameters are boxing inside an array/list/collection of objects.
This is the worst solution because our poor string and int have to be boxed into
two objects and then unboxed into the original types. In this manner we lost type
safety and performance.
3) The return parameters are enclosed in a typed structure or in a class. Very OOP!
public struct ParametersStructure
{
public string param1;
public int param2;
}
public ParametersStructure ReturnTwoParams()
{
ParametersStructure ps;
ps.param1 = "string value";
ps.param2 = 10;
return ps;
}
private void Test()
{
ParametersStructure ps= ReturnTwoParams();
string param1 = ps.param1;
int param2 = ps.param2;
}
|
This is the OOP way. Very boring to code. Every function that returns something
more than a parameter, needs all this coding. But the worst thing is that our project
starts to fill up of useless classes and structures. I'm saying that this kind of
types are useless because they don't represent an entity but they are only a vehicle
to workaround a limitation of C#.
4) The return parameter is a tuple of generics.
A tuple is a function that links various attributes to structured values extracted
from one or more relation's domains.
In C# we can mimic the tuple function using generics to maintain type safety.
For first we have to create a Tuple class like this one:
public class Tuple<T1>
{
public T1 param1;
public Tuple(T1 t1)
{
param1 = t1;
}
}
public class Tuple<T1, T2> : Tuple<T1>
{
public T2 param2;
public Tuple(T1 t1, T2 t2) : base(t1)
{
param2 = t2;
}
}
public class Tuple<T1, T2, T3> : Tuple<T1, T2>
{
public T3 param3;
public Tuple(T1 t1, T2 t2, T3 t3) : base(t1, t2)
{
param3 = t3;
}
}
|
First Class (Tuple<T1>) is useful only for inheritance because we don't have
any problem to return one single parameter.
Second and third classes are more interesting. Let's see how our problem could be
solved.
public Tuple<string,int> ReturnTwoParams()
{
Tuple<string, int> retParam =
new Tuple<string,int>("string value", 10);
return retParam;
}
private void Test()
{
Tuple<string, int> retParam = ReturnTwoParams();
string param1 = retParam.param1;
int param2 = retParam.param2;
}
|
Simple and type safe! Our return parameter is a tuple that contains our two variables.
We can accede to both variables in a type safe manner without casting and without
danger of runtime errors.
The Tuple class, for his nature, could be written one time for the entire project
and used by any methods.
If you need more than three return parameters, you can write the Tuple<T1, T2,
T3, T4> class and so on.
Thanks to
Luca Bolognese and
his wonderful blog for this nice trick.