tags:

views:

198

answers:

4

I find myself in the situation requiring this

public static void Fill(this SomeClass c, params out object[] p)

and calling it as

c.Fill(out i, out i2, out sz, out i3, out sz2);

However i get the error error CS1611: The params parameter cannot be declared as ref or out

How can i pass in variable length arguments and make them writeable? All of these are a mixture of ints and strings

+2  A: 

You could pass an array by ref.

Edit:

This would of course change your calling method:

object[] array = new object[] { i, i2, sz, i3, sz2 };
c.Fill(ref array);
Gnoome
put all in one basket and send this new one!!
viky
problem here is array will change but i1, i2 etc wont. Copying the value back to the variable defaults the purpose of the lazy method i would like.
acidzombie24
Have you tried it? All array types are implicitly derived from System.Array, which itself is derived from System.Object. This means that all arrays are always reference types which are allocated on the managed heap, and your app's variable contains a reference to the array and not the array itself.
Gnoome
@Gnoome: if `Fill` sets `array[0]` to 42 then `i` will *not* receive the value.
dtb
+4  A: 

There is no technical need for out here. This works:

void Fill(object[] p)
{
    p[0] = 1;
    p[1] = 42;
    p[2] = "Hello";
    p[3] = -1;
    p[4] = "World";
}

object[] p = new object[5];
foo.Fill(p);
i = (int)p[0];
i2 = (int)p[1];
sz = (string)p[2];
i3 = (int)p[3];
sz2 = (string)p[4];


You could return your values as Tuple:
(define your own tuple class if you're not using .NET4.0)

static Tuple<int, string> Fill()
{
    return new Tuple(42, "Hello World");
}

and then define extension methods to unpack tuples:

public static class TupleExtensions
{
    public static void Unpack<T1, T2>(
        this Tuple<T1, T2> tuple,
        out T1 item1,
        out T2 item2)
    {
        item1 = tuple.Item1;
        item2 = tuple.Item2;
    }
}

Then you can write this:

int i;
string sz;

foo.Fill().Unpack(out i, out sz);
dtb
Thats the problem. The point was to not do this and be lazy like calling a simple function instead of horrible one line typecast or function calls per statement :(
acidzombie24
close but how would i unpack a variable length turple?
acidzombie24
Tuples are, by definition, not of variable length.
dtb
+7  A: 

You can't have it treat the arguments as out (or ref) and make use of the params feature at the same time. It simply doesn't work. The best you can do is to create an array parameter, make the array out, declare an array variable and call the method passing the array, then inspect each element manually by index.

Foo(out object[] data) {...}
object[] result;
Foo(out result);
// look at result[0], result[1], result[2] etc

So: you cannot do what you want. Even if you could, ref / out never work unless there is an exact match between data type, so it would still have to be:

object o1, o2, o3, o4;
Foo(out o1, out o2, out o3, out o4);
// cast o1, o2, o3, o4

Which still isn't what you want.

Marc Gravell
Thats unfortunate.
acidzombie24
+1  A: 

As others have said, you can't use params and out together. You have to construct an array at the call site.

This is because params tells the compiler to do the same thing - construct an array from the specified arguments. Unfortunately, when the compiler creates the array, you don't get a reference to it; even if the variable is written with a new array, you can never get to it.

I would guess you are asking for a thin metal ruler. What problem are you trying to solve with this mechanism?

Bryan Watts
I hate when people ask for a thin metal ruler. I'm parsing text via user input. I dont know how much data i can extract and which the user wants to ignore thus i am allowing the user to pass in variable length params (and a type to say ignore this entry) which should be set to the value in the class or data pass through. Thus i want to do exactly what i asked. I can return an array but in practice i have variables that already exist and its easier to do it the way i asked.
acidzombie24
Fair enough. Since it has been established that the syntax isn't supported, can you write a type which manages this for you? By which I mean, if you could have any syntax that doesn't involve the C# team, what would it be?
Bryan Watts