How do I return 2 or more values at a time in a method?

19

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 just to package the data and to return more values.

  

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

Via Object (I believe not 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");
}
    
asked by anonymous 06.04.2017 / 13:40

4 answers

15

The class must be created if it makes sense, if the content has any special meaning, when the members are actually related and 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 most appropriate 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, making the use of Tuple<> obsolete. And so the tuples will eventually be used for more things.

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

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

So:

public (int, string) ReturnsIntAndString() {
    return (1, "two");
}

Or even better:

public (int inteiro, string texto) ReturnsIntAndString() {
    return (1, "two");
}

There are numerous advantages to doing this, including performance and memory management.

Note that in old tuples members had names Item1 , Item2 , etc. In the new ones they will only have those names if you do not name the members.

The tuple creates an anonymous new type. It can be used anywhere it fits a type, but by being anonymous it can get weird to abuse it. With the tuple we can count on structural types. So two independent tuples that have the same signature (same number of members with the same types in the same order) 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 KeyValuePair because of what I mentioned 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 listed as a key and value, it should not be used. It works? Of course, but good programmers produce semantic codes first. Obviously if you have more than two members it will not do.

My (multiple) tests in the linked tag in the response consistently gave the best result for out . Close was the language tuple and much worse 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) {
            return (int.TryParse(text, out var result), result);
        }
    }
}

See running on .NET Fiddle . Also I put it in GitHub for future reference .

    
06.04.2017 / 13:55
8

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

public KeyValuePair<int,string> GetValues() 
{
  return new KeyValuePair<int,string>(10,"xxx");
}
    
06.04.2017 / 13:59
5

Tuples are a good idea. Even more with this change coming in C # 7, this will get much more fluid and easy to read.

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

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

Example:

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

//uso
int inteiro2;    
int inteiro1 = RetornaInteiros(out inteiro2);
    
06.04.2017 / 14:02
1

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

We know you need to use more than one output parameter,

or

We chose to create more than one instance that contains the values we 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);
}
}
    
06.04.2017 / 14:54