How to return 2 or more values at once in a method?

Asked

Viewed 9,040 times

20

It is common to see examples of methods returning one value at a time. I’ve seen cases where you need to create a class only to package the data and be able to return more values.

Use the generic classes would be the best way to return 2 or more values of several types ( int and string) at once in a method?

Via Object ( I believe not to be recommended )

public class DoisInteiros
{
     public int Int1 { get; set;}
     public int Int2 { get; set;}
}
public DoisInteiros RetornaDoisInteiros()
{
     return new DoisInteiros() {Int1 = 1; Int2 = 2}

}

Using Generic Types

public Tuple<int,string> ReturnsIntAndString()
{
    return new Tuple<int, string>(1,"two");
}

4 answers

16


The class should be created if it makes sense, if the content has any special meaning, when the members are actually related and are part of a single object. Usually when it will be used in more than one place. Do not create a class just to group a set of unrelated values.

The tuple is more suitable when it only serves to return more than one value and does not produce a specific identity.

In fact C# 7 has created a new tuple system virtually rendering the use of Tuple<>. And so the tuples will end up being used for more things.

Often where creating a class makes no sense the tuple can be used. Not only are we dealing with unrelated values, but also cases where the grouped content is fleeting and matters more to its members than the set.

We can also abuse the use of tuples. There is much case that the creation of a named object makes more sense. And I’m not even talking about the obvious characteristics that a tuple cannot have because it’s not an object as behavior, for example.

Thus:

public (int, string) ReturnsIntAndString() => (1, "two");

Or better yet:

public (int inteiro, string texto) ReturnsIntAndString() => (1, "two");

It has numerous advantages to do this way, including performance and memory management.

Note that in the old tuples members had names Item1, Item2, etc. New ones will only have these names if you do not name the members.

The tuple creates an anonymous new type. It can be used anywhere a type fits, but because it is anonymous it can be weird to abuse it. With the tuple we have structural types. So two independent tuples that have the same signature (same number of members with the same types in the same order) they are compatible and it’s like one thing.

out will tend to become obsolete as well. E ref will not be used to return more than one value. Unless you need performance.

I do not recommend the KeyValuePair precisely from what I informed above. The semantics is wrong. a key and value pair is a specialization of a tuple that indicates having a key and a value. If the data is not related as a key and a value, it should not be used. Does it work? Sure, but good programmers produce semantic code first. Obviously if you have more than two members it does not serve.

My (several) code tests linked in the response provided consistently the best result for the out. Close was the language tuple and much worse the KeyValuePair.

An example:

using System;

public class Program {
    public static void Main() {
        var (deuCerto, resultado) = "123".TryParseInt32();
        if (deuCerto) Console.WriteLine(resultado);
    }
}

namespace System {
    public static class StringExt {
        public static (bool ok, int result) TryParseInt32(this string text) => (int.TryParse(text, out var result), result);
    }
}

Behold working in the ideone. And in the .NET Fiddle. Also put on the Github for future reference.

8

According to this site, which compares the "best possibilities" of returning 2 or more values in C#, the best form based on performance is the following:

public KeyValuePair<int,string> GetValues() 
{
  return new KeyValuePair<int,string>(10,"xxx");
}
  • 1

    In fact KeyValuePair not a good idea. I put on the subject in my reply.

  • Is it possible in this method by returning the tuple items instead of the information itself, would it have any way to return the variable? Example: public Keyvaluepair<int,string> Getvalues() { Return new Keyvaluepair<int,string>(variableAqui,"variableAqui"); }

5

Tuples are a good idea. Even more so with this change that comes in C# 7, this will become much more fluid and easy to read.

There is still the option to use a parameter out, if it is necessary to return few values (two or three).

Of course this depends on context, because semantically it may be wrong to use the parameter out. In this specific example (return two integers) it would make more sense to use a tuple, whereas in another specific case like the int.TryParse(out val) the use of out.

Example:

public int RetornaInteiros(out int segundoRetorno)
{
    segundoRetorno = 0;
    return 1;
}

//uso
int inteiro2;    
int inteiro1 = RetornaInteiros(out inteiro2);

2

When you want to have a return of more than one value, according to the properties of the C#:

We know that it is necessary to use more than one output parameter,

or

We have chosen to create more than one instance that contains the values you want to return.

using System;
using System.Collections.Generic;

class Program
{
    static void GetTwoNumbers(out int number1, out int number2)
    {
        number1 = (int)Math.Pow(2, 2);
        number2 = (int)Math.Pow(3, 2);
    }

    static KeyValuePair<int, int> GetTwoNumbers()
{
    return new KeyValuePair<int, int>((int)Math.Pow(2, 2),
        (int)Math.Pow(3, 2));
}

static void Main()
{
    // Use out parameters for multiple return values.
    int value1;
    int value2;
    GetTwoNumbers(out value1, out value2);
    Console.WriteLine(value1);
    Console.WriteLine(value2);

    // Use struct for multiple return values.
    var pair = GetTwoNumbers();
    Console.WriteLine(pair.Key);
    Console.WriteLine(pair.Value);
}
}
  • 1

    In fact KeyValuePair not a good idea. I put on the subject in my reply.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.