469,265 Members | 1,962 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,265 developers. It's quick & easy.

'null' references

As explained in "Using pointers vs. references"
http://groups.google.ee/group/borlan...294c7b02e8faca ,
the pointers are allowed to be null, while references must refer an existing
variable of required type. The null is normally used for making optional
parameters. But there is no way to pass null reference in C#. Something is
missing.
Jun 15 '07
76 4151

"Peter Duniho" <Np*********@nnowslpianmk.comwrote in message
news:op***************@petes-computer.local...
On Fri, 15 Jun 2007 14:04:26 -0700, Ben Voigt [C++ MVP]
<rb*@nospam.nospamwrote:
>It's a very bad idea, true, but people who use references instead of
pointers simply because "I would have to check for NULL pointers, and
references can't be NULL" are simply misinformed.

It's true. In C++ you can use casting to get around practically any
limitation intentionally put into the language.
There is no cast required.

int* p = nullptr;
int& i = *p;

I just put used cast syntax to avoid an additional line of code, the actual
conversion is implicit.
>
I don't see how that invalidates my point though. I have never written
C++ code that checks something passed by reference for null references,
nor have I ever had to maintain code written that way.

I never suggested that the reason to use references was to avoid having to
check for null pointers, but I do feel that is in fact an advantage (if
the caller wants to explicitly get around that safe-guard, that's a bug in
the caller akin to using Reflection in C# to get around a variety of
safe-guards C# puts into place), and I bristle at your implication (if not
outright accusation) that I am "misinformed" just for thinking so.
There's no explicitness in the getting around it. It can happen in
perfectly good-looking code. Thinking a reference is anything different
from syntactic sugar around a pointer *is* misinformed.

class X
{
public:
bool operator==(const X& other)
{
...
}
...
};

void use_it(T* p)
{
T t(...);
if (t == *p)
...
}

Clearly, if p is NULL, then operator== gets an invalid reference. There's
no sleight-of-hand necessary to accomplish it. Using the variable "other"
without testing if its address is NULL will have the exact same effect as
dereferencing p without checking if it is NULL. If you are using references
in your code as a means of documenting "NULL is not permitted for this
pointer", that's fine. But it is not a language restriction.

Jun 16 '07 #51

"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP*********************@msnews.microsoft.com. ..
valentin tihomirov <V_*********@best.eewrote:
Yes, both "out" and "ref" require you to use an actual variable. This
is entirely reasonable given the purpose of ref, IMO.

But you cannot read the 'out' parameter in order to accoumplish the trick
of
passing 'null' reference.

Do you remember how early on I asked you to describe what you were
trying to achieve *without referring to other languages*? I can't help
but feel this is still the only way forward in this discussion...
Here's the way to achieve it: Use a pointer, same as you would in every
other language to accomplish the same thing.

The problem isn't .NET's treatment of ref/out parameters, it is the
treatment of all pointers as unsafe. Creating a pointer is type-safe.
Dereferencing a pointer is type-safe. Comparing pointers is type-safe. The
only unsafe operation is incrementing (for any increment other than zero) a
pointer. And, it should be possible for highly trusted code to provide
bounded-pointer-iterators for arrays that can be used by safe code, and this
would also solve the problem of modifying struct members in-place in a
collection the same way it is possible with structs in arrays.

Jun 16 '07 #52
Larry Smith <no_spam@_nospam.comwrote:
I completely disagree. There's nothing inherently ugly about it at all. It's
very clean in code and C/C++ developers have been using it for decades. Most
of the time you're dealing with one or two "out" parameters only so passing
"null" is a very quick and convenient (and consistent) way to tell any
function not to fill something in. It's highly legible (self-describing) and
no extraneous flags or properties are required to control what you want
(which means more work and more code). As for it being error-prone, that
argument is almost groundless in practice. It's no more error-prone than
passing null for a non-out parameter if the function isn't designed to
handle it. Any function should be prepared to handle null even if it means a
simple Assert at the very least. For an "out" parmeter, one simple check for
null is all that's required to make it optional. I've been in the coding
trenches for almost 25 years and can't recall anytime I had an issue with
this.
Well, I still think it smacks of being completely non-OO. The values
are clearly related, so encapsulating them into a single type makes
more idiomatic sense to me.

If you could change C# to accommodate this, how would you try to do so?
Checking the out parameter with:

if (outParam == null)

would be inconsistent in my view, as everywhere else in C# that would
be checking whether the *value* of outParam was null, not whether it
was an out parameter which didn't have anywhere to store its result.
I'd prefer a new keyword to using the above syntax - and I'd prefer not
having it at all to having a new keyword.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jun 16 '07 #53
Ben Voigt [C++ MVP] <rb*@nospam.nospamwrote:
Hmm... that may be an idiom I've never come across. The first two make
absolute sense (even if they're fairly rarely required), but this one
is outside my experience.

Well, for example, Dictionary`2.TryGetValue has to return the same object
every time. It's not sufficient to copy the data into a caller-provided
object. There may be cases where the method has enough information to copy
(Dictionary couldn't even if it wanted to), but you want to share the same
object every time anyway. I think this is part of the Flyweight pattern.
Sort of - I certainly wouldn't have thought of it in terms of demanding
referential equality, just in terms of "returning an object" (yeah, a
reference really). But I'm glad I understand all your points now :)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jun 16 '07 #54

"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP*********************@msnews.microsoft.com. ..
Ben Voigt [C++ MVP] <rb*@nospam.nospamwrote:
Hmm... that may be an idiom I've never come across. The first two make
absolute sense (even if they're fairly rarely required), but this one
is outside my experience.

Well, for example, Dictionary`2.TryGetValue has to return the same object
every time. It's not sufficient to copy the data into a caller-provided
object. There may be cases where the method has enough information to
copy
(Dictionary couldn't even if it wanted to), but you want to share the
same
object every time anyway. I think this is part of the Flyweight pattern.

Sort of - I certainly wouldn't have thought of it in terms of demanding
referential equality, just in terms of "returning an object" (yeah, a
reference really). But I'm glad I understand all your points now :)
Well, the alternative was, fill in the object the caller gave you by
reference... which is an anti-pattern to Flyweight.
>
--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jun 16 '07 #55
Ben Voigt [C++ MVP] <rb*@nospam.nospamwrote:
Sort of - I certainly wouldn't have thought of it in terms of demanding
referential equality, just in terms of "returning an object" (yeah, a
reference really). But I'm glad I understand all your points now :)

Well, the alternative was, fill in the object the caller gave you by
reference... which is an anti-pattern to Flyweight.
Sure - it's just not something which would normally have occurred to me
to even think of, and I just didn't get it from your original
description. No biggie.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jun 16 '07 #56
On Sat, 16 Jun 2007 10:39:15 -0700, Ben Voigt [C++ MVP]
<rb*@nospam.nospamwrote:
There is no cast required.

int* p = nullptr;
int& i = *p;

I just put used cast syntax to avoid an additional line of code, the
actual conversion is implicit.
IMHO, your example is still contrived, and semantically the error is at
the point where you've dereferenced a null pointer, as opposed to using
the reference later. But more importantly, your example abandons the
specific context in which my statement was made.

My comment was strictly about the use of a null _explicitly_ as a
parameter. You seem to have taken that as an opening to infer all sorts
of other things that I never wrote, nor never intended anyone to infer.
There's no explicitness in the getting around it. It can happen in
perfectly good-looking code. Thinking a reference is anything different
from syntactic sugar around a pointer *is* misinformed.
Whatever. Personally, I find that reference parameters in C++ help a lot
in documenting what is expected of the caller.
[...]
void use_it(T* p)
{
T t(...);
if (t == *p)
...
}

Clearly, if p is NULL, then operator== gets an invalid reference.
Again, semantically it's my opinion that the error occurs at the point of
dereference. That is, "*p" is invalid itself.

Does the use of a reference parameter prevent that? No, I never meant to
imply that it did. But the fact is that the null dereference would be an
error even without the reference parameter. That is, it's not even
related to the use of the reference parameter.

All that the use of the reference parameter does is change when the null
pointer causes the error. But semantically, the error occurred outside
the function using the reference parameter, when the null pointer was
dereferenced.

Pete
Jun 16 '07 #57
In my opinion, the error is in use_it's caller passing a NULL parameter
against the documented contract of the function, or use_it's author failing
to document that requirement. My point was simply that using a reference
parameter is not significantly different from a pointer parameter as far as
NULL handling is concerned. The one is just syntactic sugar for the other.
"Peter Duniho" <Np*********@nnowslpianmk.comwrote in message
news:op***************@petes-computer.local...
void use_it(T* p)
{
T t(...);
if (t == *p)
...
}

Clearly, if p is NULL, then operator== gets an invalid reference.
Again, semantically it's my opinion that the error occurs at the point of
dereference. That is, "*p" is invalid itself.

Does the use of a reference parameter prevent that? No, I never meant to
imply that it did. But the fact is that the null dereference would be an
error even without the reference parameter. That is, it's not even
related to the use of the reference parameter.

All that the use of the reference parameter does is change when the null
pointer causes the error. But semantically, the error occurred outside
the function using the reference parameter, when the null pointer was
dereferenced.

Pete

Jun 16 '07 #58
Peter Duniho wrote:
On Sat, 16 Jun 2007 05:53:38 -0700, valentin tihomirov
<V_*********@best.eewrote:
Larry grasped it very well. But the correct answer, which I assumed in
the
OP, is not because C# references are the same as references in other
languages. Doing so is not allowed because the pointers, which are
allowed
to refer any areas of memory where no valid objects exist including
address
0, are not supported in C#.

That makes no sense at all.
Actually, it makes sense if you know what Valentin's trying to say - it
makes perfect sense to me, at least. Valentin is talking in the OP about
a certain construct - a "dereferenced null" - that can be passed in some
languages as an argument where the parameter is declared as
pass-by-reference. The result is that any attempt to read or write the
argument in the body of the method causes an AV or null reference
exception.

In the post that you've just replied to, he's talking about a property
of verifiable code running on the CLI virtual machine, memory safety
(i.e. incorrectly typed references are impossible). He's suggesting that
the correct answer to the reason why this "dereferenced null" concept is
missing from C# is because it violates the CLI's memory safety. This
isn't true: the CLI could easily implement it safely, however it would
definitely surprise everyone to add it at this late point. In any case,
it's not a big loss that it's a missing feature of the CLI or C#.
The question of "ref" parameters has exactly
zero to do with the implementation of references vs pointers. You are
trying to apply some nonsensical, irrelevant aspect of the data type
implementation in debating a higher-level language construct.
Peter, sometimes the people you reply to do have an idea that you
haven't considered yet!

-- Barry

--
http://barrkel.blogspot.com/
Jun 17 '07 #59
Jon Skeet wrote:
Larry Smith <no_spam@_nospam.comwrote:
I completely disagree. There's nothing inherently ugly about it at all. It's
very clean in code and C/C++ developers have been using it for decades. Most
of the time you're dealing with one or two "out" parameters only so passing
"null" is a very quick and convenient (and consistent) way to tell any
function not to fill something in. It's highly legible (self-describing) and
no extraneous flags or properties are required to control what you want
(which means more work and more code). As for it being error-prone, that
argument is almost groundless in practice. It's no more error-prone than
passing null for a non-out parameter if the function isn't designed to
handle it. Any function should be prepared to handle null even if it means a
simple Assert at the very least. For an "out" parmeter, one simple check for
null is all that's required to make it optional. I've been in the coding
trenches for almost 25 years and can't recall anytime I had an issue with
this.

Well, I still think it smacks of being completely non-OO.
It's orthogonal to OO, IMO, even if OO was an unalloyed virtue, which it
most certainly isn't, IMHO. OO include methods, so it basically includes
a good chunk of the whole of structured programming - for better or
worse.
The values
are clearly related, so encapsulating them into a single type makes
more idiomatic sense to me.
What if the values you're retrieving have different costs, and you don't
want to pay the whole cost, only the cost for the bits you want?

There are plenty of alternative designs, but I don't think any of them
match the C/C++ solution in clarity or conciseness.

Some off the top of my head:
* have many methods instead of one (API bloat)
* have an auxiliary flags argument that specifies the arguments you're
interested in
* return a proxy object which calculates and caches the values on demand
(implementation overhead, runtime overhead, API bloat)
If you could change C# to accommodate this, how would you try to do so?
That's a syntax issue - it's pretty irrelevant.

-- Barry

--
http://barrkel.blogspot.com/
Jun 17 '07 #60
Larry Smith wrote:
Not only is it bad, it's undefined behaviour so it doesn't qualify as valid
C++. You can't legally dereference a null pointer nor is a null reference
legally possible.
Of course, this is a red herring as far as C# and .NET are concerned.
Implementing this such that it causes a null reference exception (just
like a null object reference) wouldn't be a problem.

It would be a surprising thing to add, so I'm quite sure it won't ever
be added, but all the same, I think this is a red herring.

-- Barry

--
http://barrkel.blogspot.com/
Jun 17 '07 #61
Barry Kelly <ba***********@gmail.comwrote:
The values
are clearly related, so encapsulating them into a single type makes
more idiomatic sense to me.

What if the values you're retrieving have different costs, and you don't
want to pay the whole cost, only the cost for the bits you want?
Then as I said before, you could specify another parameter which said
exactly what you wanted to retrieve.
There are plenty of alternative designs, but I don't think any of them
match the C/C++ solution in clarity or conciseness.
It certainly wouldn't be as concise as the C++ solution, but I'd say it
would be clearer. Currently each parameter would be doing two things:
specifying an option *and* providing somewhere to store a result. I
think it's clearer to separate those. It's a personal opinion though -
I don't think there's a right or wrong answer on that front.
Some off the top of my head:
* have many methods instead of one (API bloat)
But potentially increased clarity. Having fewer methods certainly isn't
always a good thing.
* have an auxiliary flags argument that specifies the arguments you're
interested in
* return a proxy object which calculates and caches the values on demand
(implementation overhead, runtime overhead, API bloat)
Indeed.
If you could change C# to accommodate this, how would you try to do so?

That's a syntax issue - it's pretty irrelevant.
No, it's not - not unless you think that a language should be all
things to all people. Making the language more complex is a cost in my
view, and it needs to be balanced against the benefit.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jun 17 '07 #62

"valentin tihomirov" <V_*********@best.eewrote in message
news:%2****************@TK2MSFTNGP05.phx.gbl...
>Since a "ref" parameter is essentially the same as C++'s "&" by-reference

THEY ARE NOT !!!

Look at the google newsgruop I reference
Ups, the point was to remid that C++ pointers are different from references.
Jun 17 '07 #63

"valentin tihomirov" <V_*********@best.eewrote in message
news:u$*************@TK2MSFTNGP06.phx.gbl...
>
"valentin tihomirov" <V_*********@best.eewrote in message
news:%2****************@TK2MSFTNGP05.phx.gbl...
>>Since a "ref" parameter is essentially the same as C++'s "&"
by-reference

THEY ARE NOT !!!

Look at the google newsgruop I reference

Ups, the point was to remid that C++ pointers are different from
references.
But they *aren't* different, except in a syntactic sugary kind of way.
Maybe if you consider the fact that a reference can't be redirected... but
that's the same as a const pointer (as opposed to a pointer to const data).

Jun 18 '07 #64
If they are not different, they are the same as C# refs and I can pass
'null's.
Jun 18 '07 #65
It certainly wouldn't be as concise as the C++ solution, but I'd say it
would be clearer. Currently each parameter would be doing two things:
specifying an option *and* providing somewhere to store a result. I
think it's clearer to separate those. It's a personal opinion though -
I don't think there's a right or wrong answer on that front.
Formerly, when we business did not feed us with disposable packages, we
used to buy liquid products in our tare. So, you come to dairyman, put your
package in front of him to say you do not need any milk. It is more
rational, IMO, not to provoke the party by not submitting the the package to
him (and not taking it with you to shop, in addition). The daryman should
still check if the can is provided before filling it.

You legitimate the girls who seduce men and then say "no" when the party
starts reacting. The optimization rule tells us: do not invoke resources if
you will not need them. With the extra flag, you still have to allocate the
container:

object container;
func(false, out container);

Jun 18 '07 #66
On Jun 18, 12:28 pm, "valentin tihomirov" <V_tihomi...@best.eewrote:

<snip>
You legitimate the girls who seduce men and then say "no" when the party
starts reacting. The optimization rule tells us: do not invoke resources if
you will not need them. With the extra flag, you still have to allocate the
container:

object container;
func(false, out container);
Well, that's not creating any objects. It's allocating space for the
variable, but that's all.

That's rarely the sort of API I'd write using C#, however - I'd almost
always use a return variable instead. TryParse etc use out parameters,
but I rarely use out parameters beyond that situation.

Jon

Jun 18 '07 #67
>>Yes you can. You do have to pass the correct type, however.
>>>
void Func(int &i)
{
}

void Caller()
{
Func(*(int*)nullptr);
}

It's a very bad idea, true, but people who use references instead of
pointers simply because "I would have to check for NULL pointers, and
references can't be NULL" are simply misinformed.

Not only is it bad, it's undefined behaviour so it doesn't qualify as
valid C++. You can't legally dereference a null pointer nor is a null
reference legally possible.

Is creating a reference from a pointer defined as dereferencing that
pointer, even though no access through that pointer occurs until much
later?
I don't understand your point. What I replied to was your "yes you can"
response to someone's comment that "you can't use a null for a reference
parameter in C++.". No you can't. Dereferencing a null pointer is stricly
undefined behaviour so the language's rules have nothing to say about it
(except to make it perfectly clear that is undefined). Moreover, a "null
reference" is impossible in a language where null references don't exist
according to the rules. Surely you know this so your statement is not
correct nor is any contrived example that's based on undefined behaviour.
Jun 18 '07 #68
That's rarely the sort of API I'd write using C#, however - I'd almost
always use a return variable instead. TryParse etc use out parameters,
but I rarely use out parameters beyond that situation.
I do not undesrstand what are you trying so say. Should we vote the
features, which are rarely needed, out of the language(s)?
Jun 18 '07 #69

"valentin tihomirov" <V_*********@best.eewrote in message
news:OA****************@TK2MSFTNGP03.phx.gbl...
If they are not different, they are the same as C# refs and I can pass
'null's.
C++ pointers, C++ references, and C# pointers all have the same semantics.
They can refer to an instance, NULL, or some invalid location in memory.

C# calls to ref and out arguments are different (although you will find that
C++/CLI can pass a NULL-ed reference to such a C# function without
difficulty).
Jun 18 '07 #70

"Larry Smith" <no_spam@_nospam.comwrote in message
news:OR**************@TK2MSFTNGP04.phx.gbl...
>>>Yes you can. You do have to pass the correct type, however.

void Func(int &i)
{
}

void Caller()
{
Func(*(int*)nullptr);
}

It's a very bad idea, true, but people who use references instead of
pointers simply because "I would have to check for NULL pointers, and
references can't be NULL" are simply misinformed.

Not only is it bad, it's undefined behaviour so it doesn't qualify as
valid C++. You can't legally dereference a null pointer nor is a null
reference legally possible.

Is creating a reference from a pointer defined as dereferencing that
pointer, even though no access through that pointer occurs until much
later?

I don't understand your point. What I replied to was your "yes you can"
response to someone's comment that "you can't use a null for a reference
parameter in C++.". No you can't. Dereferencing a null pointer is stricly
undefined behaviour so the language's rules have nothing to say about it
(except to make it perfectly clear that is undefined). Moreover, a "null
reference" is impossible in a language where null references don't exist
according to the rules. Surely you know this so your statement is not
correct nor is any contrived example that's based on undefined behaviour.
What I'm saying is that for code like:

void fn(int* p)
{
WaitForSingleObject(semaphore);
*p++;
ReleaseSemaphore(semaphore);
}

Clearly the above is not exception safe, and if p is NULL or otherwise
invalid to cause an access violation, you will leak semaphore counts. To
say that null and invalid references don't exist suggests that if you would
just change (int* p) to (int& i) the function would be unable to fail and
therefore correctly manages the semaphore, but this is a bogus argument.
The reference version of the function can still throw an access violation
and still needs to be coded for exception safety. This is what I mean when
I say that people who use references to avoid the problems associated with
invalid pointers are misinformed.
Jun 18 '07 #71
What I'm saying is that for code like:
>
void fn(int* p)
{
WaitForSingleObject(semaphore);
*p++;
ReleaseSemaphore(semaphore);
}

Clearly the above is not exception safe, and if p is NULL or otherwise
invalid to cause an access violation, you will leak semaphore counts. To
say that null and invalid references don't exist suggests that if you
would just change (int* p) to (int& i) the function would be unable to
fail and therefore correctly manages the semaphore, but this is a bogus
argument. The reference version of the function can still throw an access
violation and still needs to be coded for exception safety. This is what
I mean when I say that people who use references to avoid the problems
associated with invalid pointers are misinformed.
According to the standard (8.3.2[4])

"... a null reference cannot exist in a well-defined program, because the
only way to create such a reference would be to bind it to the "object"
obtained by dereferencing a null pointer which causes undefined behaviour".

I understand your point but your own argument is what's "bogus". As soon as
you engage in undefined behaviour then all bets are off. If you define the
above function as taking a reference arg then the undefined behaviour occurs
the moment someone tries to dereference an invalid pointer. That has nothing
to do any function you may be calling at the time. The undefined behaviour
occurs before the function has even started so how can it protect itself.
There is no valid way. Everything might blow up before the function even
begins but the entire environment should be considered corrupt even if it
does start. Your attempt to "protect" the function would therefore be
unreliable but that's beside the point. An "invalid reference" doesn't exist
which is the point. Null pointers do however. So do invalid pointers which
are legal so long as you don't dereference them. The pointer version of the
function would therefore have to protect itself while the reference version
has nothing to protect itself against (since invalid references don't
exist). Even for the pointer version however, it can't protect itself
against an invalid (non-null) pointer using any standard technique noting
that an "access violation" isn't even guaranteed. Nothing is guaranteed and
standard C++ can't even catch these types of so-called "exceptions". A
reference parameter is therefore inherently safe unlike a pointer parameter
since null references don't exist so a reference parameter can never refer
to an invalid object by definition. Pointers legally can however so
dereferning an invalid pointer isn't safe (which is your point) but that has
nothing to do with passing the dereferenced value as a reference arg. I
therefore suggest that you're the one who's misinformed.
Jun 18 '07 #72
valentin tihomirov <V_*********@best.eewrote:
That's rarely the sort of API I'd write using C#, however - I'd almost
always use a return variable instead. TryParse etc use out parameters,
but I rarely use out parameters beyond that situation.

I do not undesrstand what are you trying so say. Should we vote the
features, which are rarely needed, out of the language(s)?
We should consider the cost in complexity of adding features to a
language against the benefit they provides. That's how you stop a
language from trying to be all things to all people - which always
fails.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jun 18 '07 #73

"Larry Smith" <no_spam@_nospam.comwrote in message
news:Oq**************@TK2MSFTNGP06.phx.gbl...
>What I'm saying is that for code like:

void fn(int* p)
{
WaitForSingleObject(semaphore);
*p++;
ReleaseSemaphore(semaphore);
}

Clearly the above is not exception safe, and if p is NULL or otherwise
invalid to cause an access violation, you will leak semaphore counts. To
say that null and invalid references don't exist suggests that if you
would just change (int* p) to (int& i) the function would be unable to
fail and therefore correctly manages the semaphore, but this is a bogus
argument. The reference version of the function can still throw an access
violation and still needs to be coded for exception safety. This is what
I mean when I say that people who use references to avoid the problems
associated with invalid pointers are misinformed.

According to the standard (8.3.2[4])

"... a null reference cannot exist in a well-defined program, because the
only way to create such a reference would be to bind it to the "object"
obtained by dereferencing a null pointer which causes undefined
behaviour".

I understand your point but your own argument is what's "bogus". As soon
as you engage in undefined behaviour then all bets are off. If you define
the above function as taking a reference arg then the undefined behaviour
occurs the moment someone tries to dereference an invalid pointer. That
has nothing to do any function you may be calling at the time. The
undefined behaviour occurs before the function has even started so how can
it protect itself. There is no valid way. Everything might blow up before
the function even begins but the entire environment should be considered
corrupt even if it does start. Your attempt to "protect" the function
would therefore be unreliable but that's beside the point. An "invalid
reference" doesn't exist which is the point. Null pointers do however. So
do invalid pointers which are legal so long as you don't dereference them.
The pointer version of the function would therefore have to protect itself
while the reference version has nothing to protect itself against (since
invalid references don't exist). Even for the pointer version however, it
can't protect itself against an invalid (non-null) pointer using any
standard technique noting that an "access violation" isn't even
guaranteed. Nothing is guaranteed and standard C++ can't even catch these
types of so-called "exceptions". A reference parameter is therefore
inherently safe unlike a pointer parameter since null references don't
exist so a reference parameter can never refer to an invalid object by
definition. Pointers legally can however so dereferning an invalid pointer
isn't safe (which is your point) but that has nothing to do with passing
the dereferenced value as a reference arg. I therefore suggest that you're
the one who's misinformed.
I agree with everything you say about the standard. What I'm referring to
as uninformed, is stuff like the following (quoted from the C++ group this
week):

<blockquote>
With references we don't need to check that 'pMyPtrArgument != NULL',
so with references the code tends to be more elegant and robust, IMHO.
</blockquote>

This is absurd. With pointers, the behavior is well-defined. If someone
passes you a wild pointer, you may trample their memory or cause an access
violation, but exception-safety (combined with a check that you aren't
trashing your own stack frame) will allow your library to keep its internal
resources in a valid state. With references, you get "undefined behavior"
according to the standard, or the same behavior as pointers in practically
every implementation. That's hardly "more robust", agreed?

Jun 19 '07 #74
"valentin tihomirov" <V_*********@best.eeschrieb
>
Very easily.
function (ref a) {
if (a != null)
a = new object();
}

b = null;
function(ref b);
I don't understand the meaning of this pseudocode. What would/could be the
type of a and b?

You're not passing a null reference or null pointer here, but a variable
that contains null. Many would say it's passing a null (reference) by
reference. I understand it better as passing a varaible (not a reference).

What you seem to want, is a ref parameter where you can pass a variable
aswell as no variable. Right?
That is not possible in C#, atleast not with ref parameter. Could be
emaulated in unsafe code with pointers.

Christof
Jun 19 '07 #75
"valentin tihomirov" <V_*********@best.eeschrieb im Newsbeitrag
news:ON**************@TK2MSFTNGP05.phx.gbl...
Larry grasped it very well. But the correct answer, which I assumed in the
OP, is not because C# references are the same as references in other
languages. Doing so is not allowed because the pointers, which are allowed
to refer any areas of memory where no valid objects exist including
address 0, are not supported in C#.
references in the context of reference types actually can point to address
zero, wich is what a null reference is.
ref variables can't point to zero nor can they point to object instances,
they can only point to variables

You should not that reference variables vs. value variables in C# is totally
different from reference types vs value types.

Christof
Jun 19 '07 #76
"Larry Smith" <no_spam@_nospam.comschrieb im Newsbeitrag
news:uf**************@TK2MSFTNGP03.phx.gbl...
>The fact that you think my response isn't relevant to the thing you are
talking about is in fact the very evidence that you don't understand the
thing that you are talking about.

I haven't read the entire thread but the issue to me boils down to this.
Why isn't the following allowed:

void Func(out Whatever whatever)
{
if (whatever != null)
{
whatever = new Whatever();
}
}

Func(null);
The question is: what does whatever != null mean.
It tests if the content of the variable given by the caller is empty (has
content null).
It seems you want to test if the variable itself is zero, meaning no
variable given by the caller.

The would be a very problematic thing in a managed language like C#. The
compiler would have to check on any access to the parameter, if the
parameter really is assigned to a variable (of the correct type) or not,
maybe adding a lot of runtime checks. In C this is in the responsability of
the programmer and easily leads to very unmaintainable bugs.
Additionally C# would have to have additional syntax for checking if a
reference parameter is pointing to a variable or not. Your given syntax is
already occupied.

Christof
Jun 19 '07 #77

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

10 posts views Thread by Bodza Bodza | last post: by
99 posts views Thread by Mikhail Teterin | last post: by
10 posts views Thread by Jason Collins | last post: by
3 posts views Thread by Vincent RICHOMME | last post: by
12 posts views Thread by Joe | last post: by
27 posts views Thread by David W | last post: by
8 posts views Thread by A. Anderson | last post: by
reply views Thread by zhoujie | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.