Warped
Warped

Reputation: 43

Inline use of function returning more than one value in C#

I am used to using functions that return a single value "in-line" like so:

Label1.Text = firstString + functionReturnSecondString(aGivenParameter);

Can this be done for a function that returns two values?
Hypothetical example:

label1.Text = multipleReturnFunction(parameter).firstValue

I have been looking into returning more than one value and it looks like the best options are using a tuple, struct, or an array list.

I made a working function that retuns a struct. However the way I got it to work I need to first call the function, then I can use the values. It doesn't seem possible to make it happen all on the same line without writing another function.

multipleReturnFunction(parameter);
Label1.Text = firstString + classOfStruct.secondString;

I haven't made a function that returns a tuple or array list yet, so I'm not sure. Is it possible to call those functions and reference the return values "inline"?

I appreciate your feedback.

Upvotes: 3

Views: 1522

Answers (5)

Ken Kin
Ken Kin

Reputation: 4693

C# doesn't have Inline functions, but it does support anonymous functions which can be closures.

With these techniques, you can say:

var firstString=default(String);
var secondString=default(String);

((Action<String>)(arg => {
    firstString="abc"+arg;
    secondString="xyz";
}))("wtf");

label1.Text=firstString+secondString;

Debug.Print("{0}", label1.Text);

((Action<String>)(arg => {
    firstString="123"+arg;
    secondString="456";
}))("???");

label1.Text=firstString+secondString;

Debug.Print("{0}", label1.Text);

or name the delegate and reuse it:

var firstString=default(String);
var secondString=default(String);

Action<String> m=
    arg => {
        firstString="abc"+arg;
        secondString="xyz";
    };

m("wtf");
label1.Text=firstString+secondString;
Debug.Print("{0}", label1.Text);

m("???");
label1.Text=firstString+secondString;
Debug.Print("{0}", label1.Text);

So, do you really need a method returns multiple values?

Upvotes: 1

Kirill Shlenskiy
Kirill Shlenskiy

Reputation: 9587

I have a grotty hack for exactly this type of scenario - when you want to perform multiple operations on the return value without defining an extra variable to store it:

public static TResult Apply<TInput, TResult>(this TInput input, Func<TInput, TResult> transformation)
{
    return transformation(input);
}

... and here's the reason it came about in the first place:

var collection = Enumerable.Range(1, 3);

// Average reimplemented with Aggregate.
double average = collection
    .Aggregate(
        new { Count = 0, Sum = 0 },
        (acc, i) => new { Count = acc.Count + 1, Sum = acc.Sum + i })
    .Apply(a => (double)a.Sum / (double)a.Count); // Note: we have access to both Sum and Count despite never having stored the result of the call to .Aggregate().

Console.WriteLine("Average: {0}", average);

Needless to say this is better suited for academic exercises than actual production code.

Upvotes: 2

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236218

Each method can return only one value. Thats how methods defined in .NET

Methods are declared in a class or struct by specifying the access level such as public or private, optional modifiers such as abstract or sealed, the return value, the name of the method, and any method parameters

If you need to return more than one value from method, then you have three options:

  1. Return complex type which will hold all values. That cannot help you in this case, because you will need local variable to store value returned by method.
  2. Use out parameters. Also not your case - you will need to declare parameters before method call.
  3. Create another method, which does all work and returns single value.

Third option looks like

Label1.Text = AnotherMethod(parameters);

And implementation

public string AnotherMethod(parameters)
{
    // use option 1 or 2 to get both values
    // return combined string which uses both values and parameters
}

BTW One more option - do not return values at all - you can use method which sets several class fields.

Upvotes: 0

Joe Brunscheon
Joe Brunscheon

Reputation: 1989

To do this inline, I think you would have to have another method that takes your struct and gives you the string you are looking for.

public string NewMethod(object yourStruct)
{
    return string.Format("{0} {1}", yourStruct.value1, yourStruct.value2);
}

Then in the page, you do this:

Label1.Text = NewMethod(multipleReturnFunction(parameter));

Upvotes: 1

Jensen
Jensen

Reputation: 3538

Alternatively, use the ref or they out keyword.

Example:

int a = 0, b = 0;
void DoSomething(ref int a, ref int b) {
    a = 1;
    b = 2;
}

Console.WriteLine(a); // Prints 1
Console.WriteLine(b); // Prints 2

It's not inline and I personally would consider a class or a struct before using the ref or the out keyword. Let's consider the theory: when you want to return multiple things, you have in fact an object that has multiple properties which you want to make available to the caller of your function.

Therefore it is much more correct to actually create an object (either by using a class or a struct) that represents what you want to make available and returning that.

The only time I use the ref or the out keyword is when using DLL imports because those functions often have pointers as their calling arguments and I personally don't see any benefit in using them in your typical normal application.

Upvotes: 1

Related Questions