tags:

views:

495

answers:

7

Hi I have C# code that is similar to this:

int someNumber;
Thing someThing;

doStuff(out someNumber);
someThing = new Thing(someNumber);

What I would like to know is if there is any way to remove the someNumber and instantiate someThing directly within the parameter arguments.

Edit the actaul code gives me back 8 out parameters but I was just trying to keep it simple so it is more like:

int someNumber1, someNumber2, somNumber3, someNumber4,
someNumber5, someNumber6, someNumber7, someNumber8;

Thing someThing1, someThing2, someThing3, someThing4,
someThing5, someThing6, someThing7, someThing8;

doStuff(out someNumber1, out someNumber2, out someNumber3, out someNumber4,
out someNumber5, out someNumber6, out someNumber7, out someNumber8);

someThing1 = new Thing(someNumber1); etc.....................
+1  A: 

Not really. You could pass someThing in as byref, so the doStuff method initialises it, but that's nasty. What you have here is fine.

You should probably just return a value from doStuff, in which case this is the best approach:

var thing = new Thing(doStuff());

Out parameters are best used when you want to implement the TryParse pattern, or when you need to return multiple values from a function call. To be honest, even then it might be best to return an object with properties containing the values you need.

Neil Barnwell
A: 

I do not think this is possible, considering doStuff does not return a value. Why do you want to do this? IMHO putting these two function calls on seperate lines is much more readable anyway, and even if it was possible, there would certainly be no performance increase.

Aistina
+3  A: 

Well, first-off, is there any reason that you can't use a regular return instead of out here? It would be cleaner (unless there is a good reason).

Then you can use:

someThing = new Thing(doStuff());
Marc Gravell
No there is multiple parameters and I didn't write the called code and don't want to wrap it.
Tim Matthews
Fair enough. In that case, I expect your current code is about the cleanest you'll get (IMO). The delegate thing is fine, but feels unnecessary...
Marc Gravell
+5  A: 

Well, if you find yourself doing this regularly, you could do something like:

public delegate void OutAction<T>(out T value);

public TResult UseOut<TIntermediate,TResult>
    (OutAction<TIntermediate> outAction,
     Func<TIntermediate,TResult> selector)
{
    TIntermediate tmp;
    outAction(out tmp);
    return selector(tmp);
}

Then call it with (note that doStuff here is a method group - the lack of () is deliberate!):

Thing someThing = UseOut(doStuff, x => new Thing(x));

I'm not necessarily saying this is a good idea, just something to consider.

EDIT: When you start getting multiple parameters, it becomes a lot harder - because the out parameter could be the first, second, third, fourth etc...

EDIT: Slightly simpler version:

public TResult ReturnOut<TResult>(OutAction<TResult> outAction)
{
    TResult tmp;
    outAction(out tmp);
    return tmp;
}

Usage:

Thing someThing = new Thing(ReturnOut(doStuff));
Jon Skeet
A: 

If you can't alter the called function, and you're unwilling to wrap it, then you're stuck with the code you have.

I'd suggest wrapping it though to clean it up. I'd have it return an int array.

GeekyMonkey
A: 

In this particular situation, can you not just return

List<Thing>

with the objectsz already instantiated?

I know this doesn't answer the actual question, but could be useful in this scenario.

ck
A: 

Similar to ck's response, if all of your someNumber variables are ints, you could have DoStuff() return a List<int> or IEnumerable<int>, then iterate over the returned list to set your Thing objects. If your someNumber variables are of different types, you could create a return type to return the collection of values. However, if all of these values are just constructor parameters for Thing objects, I'd have to agree with ck that you should really have DoStuff() return a List<Thing> or IEnumerable<Thing>.

Ryan Riley