views:

330

answers:

7

Hi,

I would like to have a function in which I will input an array and as a result i need another array and an integer value. Is this possible?

Example:

private int[] FunctionName (int[] InputArray)
{
    //some function made here
    int intResult = xxxxx
    int[] array = xxxxx

    return intResult; //but here i need also to pass the new array!
}

EDIT:

what i need is the following (updated);

I have a function that as an input takes nothing, but internally generates two items - array + integer. I need to return these two items? Can you also let me know how can I then use this items?

How this can be done?

+3  A: 

you can use "out" keyword on the parameter

hallie
can you please paste the sample code because this is new for me
mouthpiec
there is an example on the link
hallie
+4  A: 

You have two options - you either wrap the array and the integer value into a class or a structure and return an instance of it. The other option is to use out parameters - link.

Petar Minchev
Using a structure should be the logical way as the data seems to be related, so it should be a class/structure anyways.
dbemerlin
I agree. A struct/class is the most object-oriented way. It will also make the function futureproof, since it's closed to modification but open för extension. That means that you dont have to change the function signature (returnvalue/parameters) to be able to extend the function, all you need is to extend the class/struct that is passed as a parameter.
jgauffin
A: 

There are several options, using out and ref arrays, but I would not recommend them as they promote programming with side effects (meaning you don't always know where a variable may change), making your code harder to understand.

Another option is to create a class to hold the return values you need - this works well if the result you need is composed of different types (such as an int and a int[]). This is a good choice if the returned values belong together and logically belong together and you can reuse the class.

If not, you can always use the built in generic Tuple classes, which are designed to hold multiple items together:

private Tuple<int,int[]> FunctionName (int[] InputArray)
{
    int intRes = ...;
    int intArrayRes = ...'
    Tuple<int,int[]> myResult = Tuple.Create(intRes, intArrayRes);
    ....
    return myResult; 
}

You can access the values by using the various ItemX properties:

Tuple<int,int[]> result = FunctionName(myArray);
result.Item1; 'Gets the integer
result.Item2; 'Gets the integer array
Oded
He wants an integer and an array. In your example you have two integers.
Petar Minchev
@Petar Minchev - thanks for clarifying. I didn't get that from the question...
Oded
Why the downvote?
Oded
+19  A: 

You have a couple of options (in order of what would be my preference):

Create a class and return that:

class MyResult
{
    public int[] Array { get; set; }
    public int Integer { get; set; }
}

...

private MyResult FunctionName(int[] inputArray)
{
    return new MyResult { Array = ..., Integer = ... };
}

You could use a built-in type that basically makes the definition of the custom class a bit easier:

private Tuple<int[], int> FunctionName(int[] inputArray)
{
    return Tuple.Create( ..., ... );
}

You can use an out parameter:

private int[] FunctionName(int[] inputArray, out int integerResult)
{
    integerResult = 123;
    return new int[] { ... };
}

(Obviously function names and properties, etc, are just examples... I assume you'll pick more meaningful names)

Dean Harding
A little thing, but Tuple is not built in until .Net Framework 4
CaptainCasey
@CaptainCasey: good point, I was going to mention that but I forgot :)
Dean Harding
+1 for the comprehensive answer -- although I think according to the principles of writing unmaintainable code, you neglected to mention the option of setting an undocumented global for the second output value ;)
harpo
Rather than `new Tuple<int[], int>( ..., ... );`, use `Tuple.Create( ..., ... );`. This way you get all the benefits of type inference.
Porges
@Porges: Oooh! I didn't know about that! Thanks!
Dean Harding
+1, but I would probably make `MyResult` immutable (just like a Tuple), with private set accessors, and a public constructor that sets both values.
Danko Durbić
@Danko: if this is just a local function the extra code-bloat is probably not worth it. This problem crops up frequently, and if you introduce a new class for each function, your code will be less readable by virtue of including a bunch of irrelevant boilerplate.
Eamon Nerbonne
Incidentally, I'd recommend using a struct for such a temporary container, rather than a class; and *not* to use properties but to use public fields - structs can't be null, which reduces one possible error cause, and properties merely add boilerplate but no functionality - you're dealing with a behaviorless container, and a field is the appropriate vehicle for that.
Eamon Nerbonne
(in 3.5) Would it not also be acceptable to simply return a `new object { int[], int }` and forego defining it as a new class? I've done this before when I am simply using a method once and have no need to reuse or define it further.
JYelton
+8  A: 

Try using a Tuple type. It is meant to pair related values without having to define a new type.

public Tuple<int[],int> MyFunction(int[] inputArray) {      
  ...
  int[] resultArray = ...
  int resultValue = ...;
  return Tuple.Create(resultArray,resultValue);
}

You can then access the values through the Item1 and Item2 properties.

Tuple<int[],int> tuple = MyFunction(myArray);
int[] array = tuple.Item1;
int value = tuple.Item2;

References

JaredPar
should I add some references?
mouthpiec
@mouthpiec added a few
JaredPar
Tuples are nice and quick to code, but they reduce the readability of the code because you are forced to reference properties "Item1" and "Item2". I would take the time to write a struct as suggested in other answers below.
Dr Herbie
+1  A: 

Possible. Use structs.

struct retArguments{
    public int result;
    public int array[];
} ;

Also you can visit http://msdn.microsoft.com/en-us/library/aa288471%28VS.71%29.aspx

Judas Imam
@JaredPar - that's actually more valid C#(except for the semicolon) than C++, which doesn't have method level accessibility specifier and C, where there is no `public` keyword at all.
Igor Zevaka
@Igor, the text of the answer changed since I posted my original comment (now deleted). It had a typedef call.
JaredPar
Oh, right. No worries then. I thought you were referring to the semicolon.
Igor Zevaka
+1  A: 

There are three easy ways to do this:

First method:

//use a struct to wrap values:
struct returnPair { public int number; public int[] array; }
private returnPair MyFunction(int arg1) {
   return new returnPair { number = ...., array = ...., };
}

Prefer struct to class because it is passed by value and thus avoids some mutability issues, and also avoids dealing with null. Prefer fields to properties because fields are shorter to declare and have no downside in this use-case.

Second method:

Use a tuple via Tuple.Create(....,....) - this is explained in other answers.

Third method:

Use a continuation/callback. Don't overdo it; but sometimes this is a good alternative; particularly when you want to "return" multiple items but can't easily use the yield return strategy, such as when dealing with heavily recursive functions, or enumerating more than once isn't supported. It also has the advantage of permitting quite readable calls - better than tuples in C#.

private void MyFunction(int arg1, Action<int, int[]> yieldF) {
   yieldF(....num, ....arr);
   yieldF(....num2, ....arr2); //and again...
}
//call like this note that unlike a tuple params are labelled and readable,
//basically like a foreach loop with multiple loop variables:
MyFunction(3+4+5, (intp, arrp) => {
    Do-My-Side-Effect
});

Sneaky Method :-)

If you're sneaky (not recommended) you can even combine the first and third options and abuse type-inference to get named parameters wrapped in an auto-generated readonly class :-)

private T MyFunction<T>(int arg1, Func<int, int[], T> yieldF) {
   return yieldF(....num2, ....arr2); //and again...
}
//...
var anontuple = MyFunction(3+4+5, (intp, arrp) => new { IntP = intp, ArrP = arrp, });
int foobar = anontuple.IntP + anontuple.ArrP[0];//with intellisense...
Eamon Nerbonne