Previous Available Solutions
- Out parameters: They don’t work with async methods.
- System.Tuple<...> Require an allocation of a tuple object.
- Custom-built transport type for every method: A lot of code overhead.
- Anonymous types returned through a dynamic return type: High performance-overhead and no static type checking.
A Better Way (From C#7)
Let's say we are having a class Users, with a lot of fields, like Name, FirstName, Department, PhoneNumber, CurrentWorkingOnStatus, Email,...
Inside your app, on many occasions, you request to have the FirstName and the CurrentWorkingOnStatus.
The User Class
public sealed class User
{
public int id { get; set; }
public string Name { get; set; }
public string FirstName { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Status { get; set; }
/// Many Other fields
public User() { }
public User(int userid) { }
public void Deconstruct(out string name, out string status)
{
name = FirstName;
status = Status;
}
public static User GetCurrentUserStatus(int userid)
{
return new User() {FirstName= "Frederik"
, Status = "Building CodeHelper NuGet Packages" };
}
}
The
Deconstruct
method lets you unpackage all the items in a tuple in a single operation but can also be used with your class!
The Code
The code will call GetCurrentUserStatus method, the return will be "deconstructed" into the 2 variables
userName
and
userStatus
.
var (_userName, _userStatus) = User.GetCurrentUserStatus(123);
Console.WriteLine($"{ userName} is working on {userStatus}");
In case you want to get the full class data back, with access to all properties ad methods, you still can do it
User _trending = User.GetCurrentUserStatus();
///-- You have access to a properties
Multiple Deconstruct Methods?
Yes, it is possible to create multiple deconstruct methods, as long as they have a different number of out parameters
Add the following method to the user class
public void Deconstruct(out string name, out string email, out string phone) {
name = Name + " " + FirstName;
email = Email;
phone = Phone;
}
Add the following code to your app
var (_user, _email, phone) = User.GetContactinfo(123);
Console.WriteLine($"{user} can be contacted by phone {_phone}");
Solution without the Deconstruct Method
It is not always the best way to create many deconstruct methods, you can return multiple values from your class methods directly
Add the following method the user class
public static (string name, string firstname) GetUserName()
{
return ("Van Lierde", "Frederk");
}
Add the following code to your app
var (_name, _fname) = User.GetUserName();
Console.WriteLine($"Coder: {name} {fname}");
Benchmark
| Method | Mean | Error | StdDev | Median | Allocated |
|----------------- |---------:|---------:|---------:|---------:|----------:|
| returnDestructor | 15.72 ns | 0.808 ns | 2.357 ns | 15.87 ns | 64 B |
| returnClass | 18.15 ns | 1.288 ns | 3.757 ns | 16.52 ns | 64 B |
Conclusion
These C# features make your code more readable, understandable and it is a litte faster