"ref object a" <> "ByRef a As Object" ???

D

Dr Duck

GDay all,

Something seems odd to me....
I wrote a simple C# function

public void bind(ref object a, ref object b, bool atob)
{
if(atob)
b = a;
else
a = b;
}

I call it from a windows app.

string data = "moo";
bind(ref (object)this.Text, ref (object)data, false);

As I expected I got Error CS1510 "A ref or out argument must be an
lvalue".
Here is what I didnt't expect, when I wrote a vb.net equivilant:

Public Sub bind(ByRef a As Object, ByRef b As Object, ByVal atob As
Boolean)
If (atob) Then
b = a
Else
a = b
End If
End Sub

and call it from a windows app:

Dim data As String = "moo"
bind(Me.Text, data, False)

Not only did it compile it also executed and worked - the forms title
was changed to "moo".

Why does VB.NET not spit the dummy?
Is it possible to coax C# into doing whatever vb did?

-DM
 
J

Jon Skeet [C# MVP]

Here is what I didnt't expect, when I wrote a vb.net equivilant:

Public Sub bind(ByRef a As Object, ByRef b As Object, ByVal atob As
Boolean)
If (atob) Then
b = a
Else
a = b
End If
End Sub

and call it from a windows app:

Dim data As String = "moo"
bind(Me.Text, data, False)

Not only did it compile it also executed and worked - the forms title
was changed to "moo".

Why does VB.NET not spit the dummy?
Is it possible to coax C# into doing whatever vb did?

I've had a look at what VB.NET does under the covers, and basically it
creates temporary objects, passes those by reference, and then sets
data and Me.Text to the results afterwards. Utterly horrible, if you
ask me... but it only does it that way if the parameters are either
properties or subtypes of the formal parameter types.
 
G

Guest

Thanks Mate

I agree this "late bound tempory object" [made up term] thing sounds Horrible

I can't see the rational behind it

It sounds like it would cause a lot of problems in a multi threaded app
- assignment after the function call exits not being semaphore aware..
- a process comunicating to another it had modified the object referenced as a parameter
but the modification is not apparent as the process has not exited yet...

-DM
 
C

Cor Ligthert

Hi Jon,

I was yesterday suprissed reading that you did in the thread C# learner give
an advice to look for VB.net, that I never did expect, however you sees how
things can change. (no comments needed, I most probably know them already)

:)

However when this message would come in the newsgroup languages.VB it would
get a lot of comments.

1. passing "by ref" from an Object, did you not try once to get me in a
discussion about boxing?.
2. passing as an Object
3. not Option Strict On.

I understand that it is a theoretical question, however I did want to add
this, because I did not see it in your comment, while this program will run
probably 10 times as slow as it could be.

What is something you make me always attent on when I forget by instance to
Xor a bit and do an "if" instead.

(And this part is not the area I like)

:)

Cor
 
J

Jon Skeet [C# MVP]

Cor Ligthert said:
However when this message would come in the newsgroup languages.VB it would
get a lot of comments.

1. passing "by ref" from an Object, did you not try once to get me in a
discussion about boxing?.

Um, can't remember... is it important? There's no boxing going on here,
as there are no value types.
2. passing as an Object

What about it?
3. not Option Strict On.

Ah - didn't check that one. (Silly default, to have it off.) Yup, that
improves things *slightly*. It doesn't stop you from passing a property
by reference, although it does stop you from passing a string parameter
by reference to a method accepting the parameter as an object by
reference. In other words, it gets rid of half of the nastiness, but
not all of it.
I understand that it is a theoretical question, however I did want to add
this, because I did not see it in your comment, while this program will run
probably 10 times as slow as it could be.

I'm not sure I'd go along with that bit. It's not like it's using
reflection anywhere, for instance - it's just fetching a property and
assigning it again afterwards, which may *sometimes* be expensive, but
certainly doesn't have to be.
What is something you make me always attent on when I forget by instance to
Xor a bit and do an "if" instead.

(And this part is not the area I like)

No idea what you meant by that, but never mind.
 
C

Cor Ligthert

Hi Jon,
This are not the subjects (area) I like I said, so when I am wrong, I can
this time (at start) only believe you, however in VB is an object normaly
passed by value.

Because that value is its reference. I thought that when you do a passing by
reference, you are boxing that value (which is the reference).

However I am not sure about it, because I never would think about to pass a
reference of a reference.

Cor
 
J

Jon Skeet [C# MVP]

This are not the subjects (area) I like I said, so when I am wrong, I can
this time (at start) only believe you, however in VB is an object normaly
passed by value.

Because that value is its reference. I thought that when you do a passing by
reference, you are boxing that value (which is the reference).

No, you aren't. Boxing is an entirely different concept. Boxing takes a
value type, and creates a new object on the heap containing that value.
It has nothing to do with pass-by-reference semantics.
However I am not sure about it, because I never would think about to pass a
reference of a reference.

Why not? It makes perfect sense in some situations.

See http://www.pobox.com/~skeet/csharp/parameters.html for more general
discussion of what pass-by-reference and pass-by-value mean, admittedly
in C# terms.
 
C

Cor Ligthert

Hi Jon,

Because about some things I readed from Jay B Harlow I am not sure of your
message.

However I cannot deny it now. So maybe, ( because it does not intrest me
that much) I will investigate it deeper and come back on this subject.

However it was intresting that you do not agree with it, makes investigating
maybe something I will do.
Why not? It makes perfect sense in some situations.

I have done in past a lot of references of pointers, however until now I see
in VB.net no pratical use of it.

Cor
 
J

Jon Skeet [C# MVP]

Cor Ligthert said:
Because about some things I readed from Jay B Harlow I am not sure of your
message.

Which things, out of interest? Which thread?
However I cannot deny it now. So maybe, ( because it does not intrest me
that much) I will investigate it deeper and come back on this subject.

However it was intresting that you do not agree with it, makes investigating
maybe something I will do.

I'll look at it myself - if you could let me know what Jay's said.
I have done in past a lot of references of pointers, however until now I see
in VB.net no pratical use of it.

Here's an example I've used before:

public void SplitName (string wholeName, out string firstName,
out string lastName)

("out" and "ref" parameters are very similar, I hope you'll agree)

So for instance:

string first;
string last;

SplitName ("Jon Skeet", out first, out last)

would end up with first="Jon" and last="Skeet".

I'm sure you can think of similar situations.

Personally I don't use out/ref parameters very often anyway, but when I
do they're just as likely to be reference types as value types.
 
C

cody

public void bind(ref object a, ref object b, bool atob)
{
if(atob)
b = a;
else
a = b;
}

I call it from a windows app.

string data = "moo";
bind(ref (object)this.Text, ref (object)data, false);

As I expected I got Error CS1510 "A ref or out argument must be an
lvalue".


The question is: Why isn't that allowed?
 
J

Jon Skeet [C# MVP]

cody said:
The question is: Why isn't that allowed?

Because it would be completely against the way that pass by reference
works (when not considering remoting, etc), namely that the method
being called ends up using the same memory slot for the formal
parameter as for the actual parameter that the calling method passed
in.

I for one am glad that C# *doesn't* allow such behaviour.
 
C

cody

As I expected I got Error CS1510 "A ref or out argument must be an
Because it would be completely against the way that pass by reference
works (when not considering remoting, etc), namely that the method
being called ends up using the same memory slot for the formal
parameter as for the actual parameter that the calling method passed
in.

I for one am glad that C# *doesn't* allow such behaviour.


I understand that a ref argument has to be an lvalue but I don't understand
why a cast expression is not lvalue.

void Foo(ref object obj)
{
obj=null;
}

string s = "test";
Foo(ref(object)s);

Why isn't that allowed? Has the casted object s a new address or what?
In c++,

void Foo(int ** n)
{
*n=0;
}

float * f = new float;
*f = 1.0f;
Foo((int**)&f);

worked, and that is semantically exactly the same: passing a reference as
reference.
 
J

Jon Skeet [C# MVP]

cody said:
I understand that a ref argument has to be an lvalue but I don't understand
why a cast expression is not lvalue.

It's because it's the result of an operation, it's not a variable on
its own. It's just like (i+1) isn't an lvalue, but i is (assuming i is
a variable, of course).

You can't assign to cast variables elsewhere, can you? You can't say:

((object)s)="hello";

or (worse)

((object)s)=new object();
void Foo(ref object obj)
{
obj=null;
}

string s = "test";
Foo(ref(object)s);

Why isn't that allowed? Has the casted object s a new address or what?

Consider if it were allowed, but if Foo were written as:

void Foo (ref object obj)
{
obj = Encoding.ASCII;
}

Now, that would surely have to throw an exception, wouldn't it? But
would we really want the overhead of checking type safety every time we
assigned a new value to obj?
In c++,

void Foo(int ** n)
{
*n=0;
}

float * f = new float;
*f = 1.0f;
Foo((int**)&f);

worked, and that is semantically exactly the same: passing a reference as
reference.

Well, it's actually passing a pointer to a pointer by value, but yes,
the effect is much the same. I don't know whether or not C++ would
actually let you pass *by reference* in a dodgy way though.

But yes, C++ lets you shoot yourself in the foot. It lets you pass
pointers around and then assign completely different types willy-nilly.
That's one of the reasons I use C# rather than C++. I'm quite happy
with it keeping me safe.
 
D

Dr Duck

Thanks Joh et al,

your first reply answed the question.
Somehow my last reply here did not work :(
I for one am glad that C# *doesn't* allow such behaviour.
me too, but a object proxy to a accesor would be an interesting
tool.....

I am disturbed by vbs behaviour and can't see the reasoning behing it,
can anbodey see the logic?

I am curious how the vb tempory-object-wanabee-a-reference would work
in multitreaded apps.

Some senarios where I see porblems:

tread1 modifies a byref object and comunicates to thread 2 that the
object has been modified and is now ready for thread2s use. However
thread 2 changes the object before thread1 exits. End result thread 1
exits and the object is now modified to the state which tread two was
expecting and the work of thread2 is undone.

The post function exit binding may not adhear to our semaphore scemm
(functions tend to release semaphores before exiting). Possible
solution semaphore to byref parameter is also implemented as a byref
parameter ensuring a lock during the post function stuff...

thanks
-DM
 
C

Cor Ligthert

Hi

When you look at the intention from the message in this thread from me to
Jon, than you can see that VB.net does not always allow this behaviour

I think that for compatible reasons with VB6 there is a feature to do those
things with late binding. That is in VB.net 2002 and VB.net 2003 default set
to Off. I hope it will be in VB.net 2005 set to standard On. However they
are adding a lot of old VB6 things, so you never know.

In this dotNet newsgroup is always told by the regulars to the people who
use VB.net to set that feature as fast as possible to On because it gives to
much change on errors in runtime.

Jon told he forgot to mention this and did correct that only in the thread
where we where discussing that

With Option Strict On in VB.net the behaviour is the same as C#.

Cor
 
C

cody

void Foo(ref object obj)
Consider if it were allowed, but if Foo were written as:

void Foo (ref object obj)
{
obj = Encoding.ASCII;
}

Now, that would surely have to throw an exception, wouldn't it? But
would we really want the overhead of checking type safety every time we
assigned a new value to obj?


OK I understand, that makes sense.
 
J

Jon Skeet [C# MVP]

Cor Ligthert said:
With Option Strict On in VB.net the behaviour is the same as C#.

No it's not - as I said in the message, VB.NET still allows you to pass
a property by reference with option strict on, it just doesn't allow
the actual parameter type to be different from the formal parameter
type.
 
J

Jon Skeet [C# MVP]

Cor Ligthert said:
Did you try the complete sample in VB with option strict on?

Yes, and that didn't work because of the type issue. However, I then
tried this:

Option Strict On

Imports System
Imports System.Windows.Forms

Class Test
Public Shared Sub bind(ByRef a As String, _
ByRef b As String, _
ByVal atob As Boolean)
If (atob) Then
b = a
Else
a = b
End If
End Sub


Public Shared Sub Main()
Dim data As String = "moo"
Dim f as New Form
bind(f.Text, data, False)
Console.WriteLine (f.Text)
End Sub

End Class

That shows a property being passed by reference, which you can't do in
C#.
 
C

Cor Ligthert

Hi Jon,
Public Shared Sub bind(ByRef a As String, _
ByRef b As String, _
ByVal atob As Boolean)

You did change it so much that it almost looks like this sample you showed
me

("out" and "ref" parameters are very similar, I hope you'll agree)

What is wrong with that (however I would not use it only to move a value)

Cor
 

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