ref parameter for any object

J

Jazper Manto

hi
i want to have a method with a ref object parameter so that i can pass any
object by reference and write output in it like code below. the problem is
it does not work in c# like i coded it. i do NOT want to use overloads!!! is
it possible? if yes, how?
thanx jazper

--- CODE ---
public void foo(ref object o)
{
if( o is int) ((int)o) = 1;
else if( o is double) ((double)o) = 3.5;
else if( o is string) ((string)o) = "test";
else throw new Exception("type not recognized!");
}
public void callfoo()
{
int i = 0;
double d = 0.0;
string s = string.Empty;
foo(ref (object)i);
foo(ref (object)d);
foo(ref (object)s);
}
 
N

Nicholas Paldino [.NET/C# MVP]

Jazper,

There are a few things going on here. You should be getting compile
errors in the calls to foo, because you must match the signature (the cast
to object violates it).

Also, when you do this:

((int) o) = 1;

That is also a compile error. In order to make this work, you need to
do the following:

public void foo(ref object o)
{
if( o is int)
o = 1;
else if( o is double)
o = 3.5;
else if( o is string)
o = "test";
else
throw new Exception("type not recognized!");
}

public void callfoo()
{
int i = 0;
double d = 0.0;
string s = string.Empty;

// An object that has the assignment.
object o = null;

// Set o, then call.
o = i;
foo(ref o);

// Set o, then call.
o = d;
foo(ref o);

// Set o, then call.
o = s;
foo(ref o);
}

This is the only way it is going to work. Depending on what you are
actually doing in foo, Generics might help in .NET 2.0 (which is in beta
right now).

Hope this helps.
 
W

Willy Denoyette [MVP]

Try this....

public void foo(ref object o)
{
if( o is int) o = 1;
else if( o is double) o = 3.5;
else if( o is string) o = "test";
else throw new Exception("type not recognized!");
}
public void callfoo()
{
int i = 0;
double d = 0.0;
string s = string.Empty;
object o = i;
foo(ref o);
o = d;
foo(ref o);
o = s;
foo(ref o);
}

Willy.
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

It is not easier to just return it?
public object foo( object o )

Anyway, your code has several things (complex and basics) involved that I
will try to explain.

Boxing and unboxing
--------------------------
when you convert a value type to a reference type ie : int to object you
create a new instance of object in the heap. this is better explained with
an example
double d = 0.0;
object o = d;
d=4;

now you have TWO double one in the heap referenced by "o" and another in the
stack "d" , therefore
d == (double)o is FALSE

now when you say foo(ref (object)i) you are CREATING a new object in the
heap (boxing) the int.

what happen is that with a ref parameter you cannot do this, a ref parameter
NEEDS to be a lvalue, meaning that it should be a expression valid in the
left part of an assignation like:
(object)i=4;
which is not valid ( you are getting the same problem in the if/else
construct you are using.

this is needed cause otherwise the reference used is lost at return , think
about it, you are creating a new instance and you are NOT keeping any
reference to it. !!!


I think that you will get several answer to this, probably one with a
better written techical english than me :)

Cheers,
 
J

Jazper Manto

hi nicholas

thanx for your answer.
with your code i have to cast in in a object and convert back because foo()
changed the object o and not the assigned type. is this not just a bit
circuitous?

public void callfoo()
{
int i = 0;
double d = 0.0;
string s = string.Empty;

// An object that has the assignment.
object o = null;

// Set o, then call.
o = i;
foo(ref o);
i = Convert.ToInt32(o);

// Set o, then call.
o = d;
foo(ref o);
d = Convert.ToDouble(o);

// Set o, then call.
o = s;
foo(ref o);
s = o.ToString();
}
 
J

Jazper Manto

hi Willy

thanx for your answer.
see my answer to nicholas, who suggested the same thing.
 
N

Nicholas Paldino [.NET/C# MVP]

Jazper,

You are right, it is, but this is the only way, since you want to pass
it by reference. Imagine you were able to pass the string instance in for
ref object, like so:

// Declare an instance of string, "s".
string s = "hello there";

// Call foo.
foo(ref s);

Then, in foo, you do this:

// Set o to an integer.
o = 1;

This is bad, because you are trying to stuff an integer into a string.
This is why this rule is in effect for parameters passed by reference.
 
J

Jazper Manto

hy ignacio

thanx for your explanations.
It is not easier to just return it?
public object foo( object o )
yes, would be but my method will have a bool as return like
Double.TryParse().

(object)i=4;
which is not valid ( you are getting the same problem in the if/else
construct you are using.
this is needed cause otherwise the reference used is lost at return , think
about it, you are creating a new instance and you are NOT keeping any
reference to it. !!!
that sounds logic but i thought that "foo(ref (object)i)" will create a
object in the heap refering to the object in the stack, which will be
assigned to the methods parameter "ref object o". i thought changing o will
change i now. when the method returns, the GC will collect the created
object in the heap. however obviously dotnet is not able to do what i meant.
never mind :)

jazper
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

thanx for your explanations.
yes, would be but my method will have a bool as return like
Double.TryParse().

No really, if you cast it already you don't have to.

if ( o is double)
return 3.5;


then of course you will have to cast it back to double: /* no tested */

d = (double) foo( (object) d);


Cheers,
 
J

Jazper Manto

This is bad, because you are trying to stuff an integer into a string.
This is why this rule is in effect for parameters passed by reference.

indeed it is. the programmer is responsible that the types must be correct
and no error is not going to happen...!
i mean the following code is possible too and also there is the programmer
responsible not to forget to instance the object. i mean it is allowed, it
will throw an exception but it is allowed...

object x = null;
x.ToString();
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,
object x = null;
x.ToString();


Of course, that synctactically and semantically is correct , and the
variable x is initialize ( to what is another thing !!! ) so it's a valid
construction.

The compiler can not keep track of how the variable is used, just think that
between those two lines can be a lot of lines where x can be used and
possible assigned ( even to null ) so it's not possible at compiler time to
know if x will be null in the second line.


cheers,
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top