tags:

views:

121

answers:

3

What I would like to do is be able to pass any number of variables into a function, manipulate those variables inside of the function, and have access to those manipulations outside of the scope of the function.

Example

void FunctionA()
{
    int x = 1;
    string s = "blah";
    int y = 4;
    FunctionB(out x, out s, out y);
    Console.WriteLine("{0}, {1}, {2}", x, s, y);
}
void FunctionB(out params object[] parameters)
{
    for(int ii = 0; ii < parameters.Length; ii++)
    {
        if(parameters[ii] is int) parameters[ii] = (int)parameters[ii] + 1;
    }
}

After calling FunctionA() the console should have "2, blah, 5" on it. Is there a way to do this short of returning an object[] and parsing out the variables I want?

For clarification, here is what I'm attempting to do. Pass a byte[] into a function along with a slew of variables. Attempt to read information out of the byte[] and assign it to the variables that were passed in. So if I had an int, a string, and another int written to a byte[] and I pass in something like:

int x, y;
string s;
byte[] info = ...;
FunctionB(info, x, s, y);
Console.WriteLine("{0}, {1}, {2}", x, s, y);

It would output the information from the byte[].

+4  A: 

No, you can't.

Here you've got a single out parameter, whereas you want several separate out parameters. C# doesn't support that via params... and params is the only way of getting a varying number of parameters, unless you want to overload it up to the maximum number of parameters you want to support.

params will always copy the values of the arguments into a new array. At that point they're disassociated from the original variables.

Jon Skeet
Doesn't FunctionB(out int a, out string b, out int c) count as several separate out parameters? Because this does work...I just can't figure out how to make the number of out parameters dynamic.
mphair
@mphair: Yes, that's several out parameters - but not via params. Apologies for being unclear. Will edit.
Jon Skeet
The reason for this is because *if it were possible to have an array of references to variables then the array could live longer than the references to variables that are on the stack.* This is a very common bug in C programs; it never happens in CLR programs because it is simply not possible to hold onto a reference like that.
Eric Lippert
@Eric, It was always especially fun if you had a C char[] on the stack and passed it as a char* to some function that wanted to keep it around for reference. I'm very happy that 'to malloc or not to malloc' is no longer a question.
Dan Bryant
A: 

Are you sure you need the out? Can you give us real code? This works from what I can tell about what you posted...

void Main()
{
    object [] f = new object []{ 1, "blah", 4 };
    Test( f );
    Console.WriteLine("{0}, {1}, {2}", f[0], f[1], f[2]);
    // output
    // 2, blah, 5 

}

void Test ( object[] parameters )
{
    for(int ii = 0; ii < parameters.Length; ii++)
    {
        if(parameters[ii] is int) 
            parameters[ii] = (int)parameters[ii] + 1;
    }
}
BioBuckyBall
The problem with that is that after I enclose the two ints and the string in the object[], I would need to parse them back out. This solution would be similar to making Test(object[]) return object[]. The idea with using the out keyword is that I wouldn't have to do any parsing...just throw some variables into it and begin using them right after.
mphair
Sorry, I fail to see the need for parsing? More code would help...
BioBuckyBall
@Lucas - By parsing, I mean having to call f[0] vs x. Also, with your code I would have to pack everything I want into an object[] before I send it to the function. This is what I'm attempting to get around.
mphair
A: 

Just so you know, your "clarification" is quite different from your original question. It sounds like you're trying to write deserialization code. First, read the MSDN Serialization docs to understand more about the functionality that .NET can provide. If creating self-deserializing objects is overkill for your particular situation, you should consider using BinaryReader to read the data:

byte[] info...
int x;
string s;
int y;

using (BinaryReader reader = new BinaryReader(new MemoryStream(info)))
{
    x = reader.ReadInt32();
    s = reader.ReadString();
    y = reader.ReadInt32();
}

Note that you may have to build up your own functions on top of BinaryReader.ReadeByte() if your encoding of data doesn't match what BinaryReader expects. Also note that a function that fills "a slew of variables" from a buffer has some code-smell... surely those variables are related in some way, and you have an opportunity to define a class (with a deserializer!) that represents whatever that concept is.

JaredReisinger
Yes, I am attempting to consolidate MemoryStream/BinaryReader/BinaryWriter calls into a common static class. After calling MemoryStream ostream = new MemoryStream(); BinaryWriter writer = new BinaryWriter(ostream); writer.Write(...); writer.Write(...);... a bunch of times, I was attempting to make a generic read/write call so that I could pass in as many arguments as I wanted and get a byte[] out...or pass in a byte[] and as many variables as I wanted to read out of the byte[]. I have the ability to serialize...I just wanted to streamline it.
mphair
Do you control the binary format you're reading? If so, leveraging the built-in .NET Serialization code will be by far the easiest. All you have to do is mark the fields to serialize, and let .NET handle the rest.
JaredReisinger