Using ref

  • Thread starter Thread starter Arjen
  • Start date Start date
 Your anger is misdirected (not to mention revealing).

I'm just flaming you, that's all.

BTW I think Pavel Minaev got the better of you, essentially pointing
out that in C++ (CLI) the distinction that Hilton makes is explictly
present in C++.net. But, this being a C# forum, perhaps you and Jon
make good points. It's all over my head anyway. After learning C, C++,
C++.NET (CLI) and now C#.NET it's all a blur, especially the way C#
deals with inhereitance --much more primitive than C++, and I barely
figured out the difference between ref and non-ref (pass by value)
just recently. This thread was good as a refresher. ANd see my other
thread why C# is flawed because you cannot pass an object using, as in
C++, a 'const' keyword to prevent it from being modified. How
primitive is that? I guess you have to be super careful in C# and not
depend on the compiler to save you.

RL
 
Hilton said:
Jon Skeet wrote:
Where did I say that they were? I said that *references* are passed by
value. Objects aren't passed at all.

You replied to Steve:

Steve Harclerode said:
The objects themselves are passed by reference anyway

No, they're not.
---

I then made the assumption that if the object wasn't passed by reference, it
is passed by value - which is it?

[zap your reply]

Jon, I totally 'see' you view on this (which seems to be consistent with
many/most others - i.e. I acknowledge that I am in the minority here). My
point is that a method works on data and I care about the data, I care about
the stuff that is in arrays, lists etc. Now, even though you assert that "C
doesn't have pass by reference at all.", for decades millions of people were
taught the difference between passing by reference and passing by value
using C, were they wrong?

If that's what they were taught, then yes.

Perhaps a shift to another language and some examples will help.

Pascal

program example;

var myArg: integer;

(* the parameter j is passed by reference, it has type "integer" *)
procedure showit(var j: integer);
begin
myArg = 42;
(* j has a value of 42 *)
end;

begin
showit(myArg);
end.


C

int myValue;
int myValue2;
int* myArg;

/* parameter j is passed by value, w/type of "int *" aka pointer to int */
showit (int* j) {
j = &myValue2;
*j = 3;
/* j now points to myValue2, the value of *j is 3 */
/* myArg STILL points to myValue, the value of *myArg is still 42 */
}
main()
{
myValue = 42;
myValue2 = 2;
myArg = &myValue;
showit(myArg);
}



Do you see the difference? When the parameter is a reference parameter
then changes to the parameter are changes to the argument. In C,
changes to the parameter never has an effect on the argument.
 
-snip differences between pass by value and pass by reference argument-
OK, back to basics and as simple as I can make it. Let use the C# code:

void Go ()
{
int x = 10;

Method (ref x);
}

void Method (ref int y)
{
y = 20;
}

I am claiming that this is exactly the same as the C code that has "Method
(&x)" (caller) and "Method (int *py)" (callee). All that is happening is
that the compiler is hiding the 'ugliness' from you, so that when you write
"y=20" (above), it really does a "*py= 20".

This is the first time I've ever seen understanding what is happening
on a machine level cause a misunderstanding....

You are ignoring what ELSE you can do in C, but can't in C# -- namely,
you can assign a different address to py.

void Method (int *py) {
int z;
py=&z;
*py = 2;
}

In C# y can never be anything but another way of saying x.

So IMHO, it is just some language/compiler smoke and mirrors, the
*same thing* is happening under the covers.

All languages and compilers are just smoke and mirrors over the
hardware. But it's important smoke and mirrors.
 
raylopez99 said:
So are you saying 'pass-by-value' is like 'constant' in C++ (which to
my newbie knowledge C# lacks) in that you can safely pass an object
to a function so it cannot be manipulated to change the original? If
so, please let me know how to do that, since honestly once I learned
C# I have yet to find how you can make a function/method take a 'read
only' copy of a class (not a primitive type, but of a class). In
fact, Googling this confirmed this fact (see below). So I don't see
how pass-by-value is any 'safer' (or read-only) than 'pass-by-value'
for a class passed. -snip
Furthermore, const can only be applied to intrinsic types.

Intrinsic = value-type variables, i.e. not classes.

Go read Jon's article on
parameters....<http://www.yoda.arachsys.com/csharp/parameters.html>.
 
Pavel Minaev said:
It is really unfortunate that C# designers chose to overload the term
"reference" for both object references and byref arguments

Not really. It means pointer in both cases. Object variables are
pointers/references to objects, byref arguments are when a
pointer/references to the argument is passed instead of the value of
the argument..
 
J.B. Moreno said:
Intrinsic = value-type variables, i.e. not classes.

Not quite - const can be applied to string (which is a reference type)
but not DateTime (which is a value type).

In fact, you can use any reference type for a constant field - but for
anything other than string, the only allowed value is null :) Basically
it's a case of whether or not the value itself counts as a constant in
C# terms.
 
Not really.  It means pointer in both cases.  Object variables are
pointers/references to objects, byref arguments are when a
pointer/references to the argument is passed instead of the value of
the argument..

There is a multitude of difference between CLI object references and
CLI managed pointers, regarding which I can only refer you to the CLI
spec. As long as we do not go down to the native code level, they are
different concepts in CLI, and that's what should matters for anything
built on top of that, such as C#; and indeed, it does - semantics of
"ref" and object references in C# are very different.

On a side note, managed pointers do not have to be used strictly for
argument passing - they can also be local variables (which is also
exposed in C++/CLI, though the fact that you can change a value of a
managed pointer variable itself - rather than whatever it points to -
is not), and even return values of methods, though the latter case is
unverifiable per ISO/ECMA spec, and verifiable in .NET only for some
very specific use cases.
 
Jon Skeet said:
Not quite - const can be applied to string (which is a reference type)
but not DateTime (which is a value type).

In fact, you can use any reference type for a constant field - but for
anything other than string, the only allowed value is null :) Basically
it's a case of whether or not the value itself counts as a constant in
C# terms.

Guess I snipped too much...

The "Furthermore, const can only be applied to intrinsic types" was (I
believe) a statement about C++ that raylopez99 found by Googling. I
was trying to do a cross-language comparison.
 
J.B. Moreno said:
Guess I snipped too much...

The "Furthermore, const can only be applied to intrinsic types" was (I
believe) a statement about C++ that raylopez99 found by Googling.

Not sure - it comes directly after a statement about C#, but it's not
very clear. Ah well...
I was trying to do a cross-language comparison.

Right.
 
J.B. Moreno said:
-snip differences between pass by value and pass by reference argument-


This is the first time I've ever seen understanding what is happening
on a machine level cause a misunderstanding....

You are ignoring what ELSE you can do in C, but can't in C# -- namely,
you can assign a different address to py. -snip-
In C# y can never be anything but another way of saying x.

Which is to say that the reference arguments/parameters are language
constructs -- it tells the compiler to behave in a certain way.

C# tries to make this unmistakable by requiring the keyword ref on both
the argument and the parameter (unlike in other languages where the
keyword is only used on the parameter).

It tells the compiler that instead of passing the value of the argument
itself, to instead pass a pointer to the argument and that inside the
function being called, the pointer to the argument isn't to be changed
and is to be automatically dereferenced whenever used.

You can call this "smoke and mirrors" if you like and say that it's all
the same underneath, but this ignores the fact that this type of smoke
and mirrors is exactly what a high level language like C or C# is -- a
way of "hiding" the underlying instructions from programmer.
 
Hilton said:
My point is that the C# call "method (ref x)" is defined by
you/Jon/community as being pass by reference, yet the C call "method
(&x)" is defined by you/Jon/community as being pass by value -
they're doing EXACTLY the same thing. Both simply take the address

That's true. They both use one level of indirection.
of x and pass it along. Does a prettier syntax changes the entire
concept? And if Microsoft has used "&" instead of "ref" in its

Apparently, according to the definition Jon is quoting from,
pass-by-reference is all about the syntax. So stop using those words (he's
undoubtedly using the official definition accepted in computer science) and
simply speak of "levels of indirection".
 
Peter said:
[...]
So, if I understand you correctly, the determination of "pass by
value" or
"pass by reference" is based on syntax and not functionality (here I
mean what actually gets passed etc).

It's based on what the language itself supports.

You can write C code that has the same effect as lambda expressions in
C#. That doesn't mean C supports lambda expressions.
[...]
Jon, is this C# code "pass by value" or "pass by reference"?

The C# code is clearly "by reference".
By your earlier claims, the C code is "pass by value".

Yes. Since C doesn't support "by reference", it would have to be.
So either:

1. The C# is "pass by value" in which case "ref" does not mean
"pass by reference", or
Nope.

2. The C# code is "pass by reference" even though exactly the same
as its C
counterpart, just a different syntax, or

It's not "exactly the same". There are important differences between
the two that you are ignoring.

"Pass by reference" is exactly syntactic sugar for adding a level of
indirection (i.e. take the address, pass the pointer).

C# has the pointer syntax as well, and just as in C++, the pointer syntax is
more powerful than the reference syntax.

It affects the CLR security system as well. When the parameter is defined
as pass-by-reference, the verifier checks that no pointer arithmetic is
performed, the reference isn't rebound, etc. This is what lets
pass-by-reference be used in partial trust scenarios even where the
functionally identical pointer passing is disallowed (the verifier isn't
smart enough to distinguish dangerous operations that break type safety --
pointer arithmetic -- from perfectly safe usage of pointers).
 
J.B. Moreno said:
-snip differences between pass by value and pass by reference
argument-


This is the first time I've ever seen understanding what is happening
on a machine level cause a misunderstanding....

You are ignoring what ELSE you can do in C, but can't in C# -- namely,
you can assign a different address to py.

so is this "pass-by-reference"?

void Func(int * const py);

Of course not, although py is now permanently set to the original actual
parameter. You can still do things like (py - arrayBase) which a C#
pass-by-reference doesn't permit. But a C++ pass-by-reference does...

void Func2(int& ry);

You can most certainly say (&ry - arrayBase) to get the exact same effect.
In C++, the reference syntax is no more and no less than syntactic sugar.
In C#, the reference syntax is much more. Calling these both by the same
name is more confusing than calling the C code pass-by-reference. There are
two "real concepts" going on:

number of levels of indirection
type-safety
 
You remind me of the people who continue to cling to the idea that
Iraq had something to do with the 9/11 attacks and that Hussein was
hiding weapons of mass destruction somewhere in his country, in spite
of absolutely no evidence in support of those ideas and in spite of
volumes of evidence to the contrary.

In other words, you've decided on your dogma and no amount of actual
facts will have any effect on your beliefs.

Unfortunately for you, Peter, here you paint yourself as the dogma, not
facts, type.

Plenty of "dual-use" explosives and biological agents were found in Iraq.
That they were found in bunkers with military gas masks nearby suggests that
they were in fact part of a WMD program. Not to mention the documented
instances of Hussein actually using WMD on large segments of his population.

Which is why we ought to restrict this group to programming.
 
The "Furthermore, const can only be applied to intrinsic types" was (I
believe) a statement about C++ that raylopez99 found by Googling. I
was trying to do a cross-language comparison.

Certainly not true. C++ 'const' can be applied to any variable of any type,
the type pointed to be any pointer or reference, and so on.

C++ 'const' is more like (but much more useful than) C# 'readonly'.
C++0x introduces 'constexpr' which is similar to (but again much more
powerful than) C# 'const'.
 
and I barely
It doesn't prevent something from being modified in C++ either.

It does, unless the callee goes out of its way to break its contract (i.e.
uses the const_cast keyword to remove the const). There's no way to turn a
pointer-to-const into a pointer-to-non-const without either a cast or a
union or some really hairy pointer arithmetic, all of which are known to
break type-safety.
More importantly, a much better way to ensure that a data structure
isn't modified is simply to make that data structure immutable. For
example, the String class is essentially "const" all the time. Works
great.

Not in C++ it isn't. No matter how immutable you make your object, C++ can
still overwrite the innards if you explicitly work to do so.
The lack of "const" for methods or their parameters doesn't make C#
any more flawed than any of the other languages people use on a daily
basis. It just makes it different from one of them.

If having "const" methods and parameters was such an important
feature, everyone would use C++ and no one would use C#, Java, VB,
etc. Odd, then, that so many people find languages other than C++
preferable, or at the very least, just as useful.

Or maybe it is something they really want, but they want garbage collection
and reflection more.

Or, more likely, all the Microsoft C# training never even mentions the
advantages of const-correctness, so they don't even know what they are
missing.
 

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

Back
Top