views:

361

answers:

3

Hello! I would like to have a function that modifies some variable list of parameters but they are all value types (int, string). There is a way to make the params keyword work with ref keyword or something close to that?

public void funcParams(params object[] list)
{
   /* Make something here to change 'a', 'b' and 'c' */
}

public void testParams()
{
    int a = 1, b = 2, c = 3;

    funcParams(a, b, c);
}

The problem is, I'm trying to make my life easier making a method that modifies the object fields. I'm doing some dynamic code generation using Cecil and I'm trying to avoid writing too much IL generated code.

To simplify I would like to pass the list of fields by reference I need to change to a function that changes them instead of changing them by generating the respective IL. Some of the parameters are nullable and make the code generation a little more painful. Making some overload methods instead of params won't be much useful in this case.

+2  A: 

No, it's not possible with a neat syntax. The reason is, internally, the runtime treats the method as a simple method taking an array argument. The compiler does the housekeeping of creating an array and filling it with the arguments specified. Since the arguments are value types, they will be copied to the array and any change to them will not affect the original variables. Other ways to accomplish it will defeat the purpose of existence of params which is a nice syntax for variable number of arguments.

Mehrdad Afshari
+8  A: 

Well, you could declare a few overloads, i.e.

public void FuncParams(ref int a) {...}
public void FuncParams(ref int a, ref int b) {...}

etc

Otherwise, you'll have to read back from the array (as params really means "implicit array"):

object[] args = {1,2,3};
funcParams(args);
Console.WriteLine(args[0]); // updated
Console.WriteLine(args[1]); // updated
Console.WriteLine(args[2]); // updated

(of course, if it only accepts ints, it would be better to use an int[] throughout)

Marc Gravell
I did elaborate a little more on my problem explaining why this approach isn't too much useful in this case, thanks anyway.
Augusto Radtke
+3  A: 

Yes. It is possible.

However, the resulting code is "unsafe" which makes it unverifiable.

That may or may not be an issue depending on your requirements.

In any case, here is the code:

using System;

namespace unsafeTest
{
    class MainClass
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            unsafe 
            {    
                int x = 0;
                int y = 0;
                int z = 0;
                bar(&x, &y, &z);
                Console.WriteLine(x);
                Console.WriteLine(y);
                Console.WriteLine(z);
            }
        }

        unsafe static void bar(params int *[] pInts)
        {
            int i = 0;
            foreach (var pInt in pInts)
            {
             *pInt = i++;
            }
        }
    }
}
Scott Wisniewski
It is a shame they need to be mutated; at a similar level of complexity, there is also varargs (http://www.eggheadcafe.com/articles/20030114.asp), but of course this doesn't allow mutation.
Marc Gravell
When I worked at Microsoft (as a dev on the VB compiler team), my office mate was a tester (also on VB). One area that was kind of a running joke was that in every test review he went to (about new language features), the question of "how does it work with ArgIterator" always came up.
Scott Wisniewski
Your comment reminded me of that.It gave me a chuckle.
Scott Wisniewski
@Scott, oh yes, the dreaded ArgIterator. QA loves that class.
JaredPar