iTayb
iTayb

Reputation: 12743

Is it possible for a function to return two values?

Is it possible for a function to return two values? Array is possible if the two values are both the same type, but how do you return two different type values?

Upvotes: 14

Views: 19681

Answers (13)

ZunTzu
ZunTzu

Reputation: 7772

with C# 7, you can now return a ValueTuple:

static (bool success, string value) GetValue(string key)
{
    if (!_dic.TryGetValue(key, out string v)) return (false, null);
    return (true, v); // this is a ValueType literal
}

static void Main(string[] args)
{
    var (s, v) = GetValue("foo"); // (s, v) desconstructs the returned tuple
    if (s) Console.WriteLine($"foo: {v}");
}

ValueTuple is a value-type, which makes it a great choice for a return value compared with a reference-type Tuple - no object needs to be garbage-collected.

Also, note that you can give a name to the values returned. It is really nice.

For that reason alone I wish it was possible to declare a ValueTuple with only one element. Alas, it is not allowed:

static (string error) Foo()
{
    // ... does not work: ValueTuple must contain at least two elements
}

Upvotes: 5

Michael Freidgeim
Michael Freidgeim

Reputation: 28435

To return 2 values I usually use Pair class from http://blog.o-x-t.com/2007/07/16/generic-pair-net-class/. If you need to return from method 2 values that describe the range, e.g. From/To or Min/Max, you can use FromToRange class.

public class FromToRange<T>
    {
        public T From { get; set; }
        public T To { get; set; }

        public FromToRange()
        {
        }

        public FromToRange(T  from, T  to)
        {
            this.From = from;
            this.To = to;
        }
        public override string ToString()
        {
            string sRet = String.Format("From {0} to {1}", From, To);
            return sRet;
        }
        public override bool Equals(object obj)
        {
            if (this == obj) return true;
            FromToRange<T> pair = obj as FromToRange<T>;
            if (pair == null) return false;
            return Equals(From, pair.From) && Equals(To, pair.To);
        }

        public override int GetHashCode()
        {
            return (From != null ? From.GetHashCode() : 0) + 29 * (To != null ? To.GetHashCode() : 0);
        }

    }

Upvotes: 0

user1421044
user1421044

Reputation:

you can try this

public IEnumerable<string> Get()
 {
     return new string[] { "value1", "value2" };
 }

Upvotes: 0

brian
brian

Reputation: 1080

All of the possible solutions miss one major point; why do you want to return two values from a method? The way I see it, there are two possible cases; a) you are returning two values that really should be encapsulated in one object (e.g. height and width of something, so you should return an object that represents that something) or b) this is a code smell and you really need to think about why the method is returning two values (e.g. the method is really doing two things).

Upvotes: 6

Dan Tao
Dan Tao

Reputation: 128327

In a word, no.

But you can define a struct (or class, for that matter) for this:

struct TwoParameters {
    public double Parameter1 { get; private set; }
    public double Parameter2 { get; private set; }

    public TwoParameters(double param1, double param2) {
        Parameter1 = param1;
        Parameter2 = param2;
    }
}

This of course is way too specific to a single problem. A more flexible approach would be to define a generic struct like Tuple<T1, T2> (as JaredPar suggested):

struct Tuple<T1, T2> {
    public T1 Property1 { get; private set; }
    public T2 Property2 { get; private set; }

    public Tuple(T1 prop1, T2 prop2) {
        Property1 = prop1;
        Property2 = prop2;
    }
}

(Note that something very much like the above is actually a part of .NET in 4.0 and higher, apparently.)

Then you might have some method that looks like this:

public Tuple<double, int> GetPriceAndVolume() {
    double price;
    int volume;

    // calculate price and volume

    return new Tuple<double, int>(price, volume);
}

And code like this:

var priceAndVolume = GetPriceAndVolume();
double price = priceAndVolume.Property1;
int volume = priceAndVolume.Property2;

Upvotes: 15

Jimmy Lyke
Jimmy Lyke

Reputation: 330

You could use the out parameter.

int maxAge;
int minAge;
public int GetMaxAgeAndMinAge(out int maxAge, out int minAge)
{
    MaxAge = 60;
    MinAge = 0;
    return 1; //irrelevant for this example since we care about the values we pass in
}

I really tend to stay away from this, I think that it is a code-smell. It works for quick and dirty though. A more testable and better approach would be to pass an object that represents your domain (the need to see two these two values).

Upvotes: 0

Sivvy
Sivvy

Reputation: 851

It is not possible to return more than one value from a function, unless you are returning a type that contains multiple values in it (Struct, Dictionary, etc). The only other way would be to use the "out" or "ref" keywords on the incoming parameters.

Upvotes: 0

Pharabus
Pharabus

Reputation: 6062

no but you can use an out parameter

 int whatitis;

string stuff = DoStuff(5, out whatitis);

 public string DoStuff(int inParam, out int outParam)
        {
            outParam = inParam + 10;
            return "donestuff";
        }

Upvotes: 1

Ikaso
Ikaso

Reputation: 2268

In C# you can return more than one value using an out parameter. See example in the TryParse method of Int32 struct. It returns bool and an integer in an out parameter.

Upvotes: 1

Tomas Vana
Tomas Vana

Reputation: 18775

You have basically (at least) two options, either you make an out parameter in addition to the return value of the function, something like T1 Function(out T2 second) or you make your own class putting these two types together, something like a Pair<T1,T2>. I personally prefer the second way but it's your choice.

Upvotes: 1

JaredPar
JaredPar

Reputation: 754715

Can a function return 2 separate values? No, a function in C# can only return a single value.

It is possible though to use other concepts to return 2 values. The first that comes to mind is using a wrapping type such as a Tuple<T1,T2>.

Tuple<int,string> GetValues() {
  return Tuple.Create(42,"foo");
}

The Tuple<T1,T2> type is only available in 4.0 and higher. If you are using an earlier version of the framework you can either create your own type or use KeyValuePair<TKey,TValue>.

KeyValuePair<int,string> GetValues() {
  return new KeyValuePair<int,sting>(42,"foo");
}

Another method is to use an out parameter (I would highly recomend the tuple approach though).

int GetValues(out string param1) {
  param1 = "foo";
  return 42;
}

Upvotes: 40

Reed Copsey
Reed Copsey

Reputation: 564413

It is not directly possible. You need to return a single parameter that wraps the two parameters, or use out parameters:

object Method(out object secondResult)
{
    //...

Or:

KeyValuePair<object,object> Method()
{
   // ..

Upvotes: 7

Nick
Nick

Reputation: 5955

Not directly. Your options are either to return some kind of custom struct or class with multiple properties, use KeyValuePair if you simply want to return two values, or use out parameters.

Upvotes: 3

Related Questions