Reputation: 12743
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
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
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
Reputation:
you can try this
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
Upvotes: 0
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
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
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
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
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
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
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
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
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
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