471,310 Members | 1,570 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,310 software developers and data experts.

Why does x.ToString() throw an error if x == null?

If we have something like this

object x = null;
MessageBox.Show(x.ToString())

we get an error. That kindof makes sense but there is no reason the
behaviour couldn't be to return an empty string. When we call x.ToString we
are really calling a function like this:

class Object
{
public static string ToString(object* Instance)
{
//code to convert the object pointer to a string
}
}

Why can't the compiler just pass in Instance as a null and let the code sort
it out. If the code wants to throw an error then it can but if it wants to
do something more useful then it can. This would be useful in some cases (I
admit they are rare but the ToString example above could potentially be used
quite often). I can think of a few cases where this could be useful, eg:

string x = null;
MessageBox.Show(x.IsNullOrEmpty.ToString())
MessageBox.Show(x.Length.ToString()) //<--- shows zero
DateTime? y;
MessageBox.Show(y.IsValid)

The interesting thing is you can define extention methods that do work on
null objects, eg

static class Extensions
{
public static bool IsSomething(this string s)
{
return !string.IsNullOrEmpty(s);
}
public static string ToStringIgnoreNull(this object s)
{
if(s == null) return string.Empty;
return s.ToString();
}
}

Then use it like this:

string x = null;
if (x.IsSomething()) MessageBox.Show(x)

or

object x = null;
MessageBox.Show(x.ToStringIgnoreNull())

Any comments?

Cheers,
Michael

Aug 27 '08 #1
19 2519
"Michael C" <mi***@nospam.comwrote in message
news:u7**************@TK2MSFTNGP03.phx.gbl...
[...] When we call x.ToString we are really calling a function like this:

class Object
{
public static string ToString(object* Instance)
{
No, not really. You can do that with extension methods (as you already
point out at the end of your message), but the real ToString is not static;
it is a virtual method that can be overridden in child classes:

class Object
{
public virtual string ToString()
{
return this.GetType().Name;
}
}

This can't work if the object is null.

Aug 27 '08 #2
Even if you declare an object, it doesn't really exist yet until you have
initialized it and the compiler has not set aside any space for it.

To say, "Look at the space for this object that I have not created yet and
tell me what it says" would naturally throw an error.

What might be possible (though I wouldn't know how to do it) would be to
define behaviors for your compiler. If x is null, then the compiler or
language could return something useful (instead of crashing or running off
into oblivion). God knows that happens to me plenty!

"Michael C" wrote:
If we have something like this

object x = null;
MessageBox.Show(x.ToString())

we get an error. That kindof makes sense but there is no reason the
behaviour couldn't be to return an empty string. When we call x.ToString we
are really calling a function like this:

class Object
{
public static string ToString(object* Instance)
{
//code to convert the object pointer to a string
}
}

Why can't the compiler just pass in Instance as a null and let the code sort
it out. If the code wants to throw an error then it can but if it wants to
do something more useful then it can. This would be useful in some cases (I
admit they are rare but the ToString example above could potentially be used
quite often). I can think of a few cases where this could be useful, eg:

string x = null;
MessageBox.Show(x.IsNullOrEmpty.ToString())
MessageBox.Show(x.Length.ToString()) //<--- shows zero
DateTime? y;
MessageBox.Show(y.IsValid)

The interesting thing is you can define extention methods that do work on
null objects, eg

static class Extensions
{
public static bool IsSomething(this string s)
{
return !string.IsNullOrEmpty(s);
}
public static string ToStringIgnoreNull(this object s)
{
if(s == null) return string.Empty;
return s.ToString();
}
}

Then use it like this:

string x = null;
if (x.IsSomething()) MessageBox.Show(x)

or

object x = null;
MessageBox.Show(x.ToStringIgnoreNull())

Any comments?

Cheers,
Michael

Aug 27 '08 #3
"jp2msft" <jp*****@discussions.microsoft.comwrote in message
news:8D**********************************@microsof t.com...
Even if you declare an object, it doesn't really exist yet until you have
initialized it and the compiler has not set aside any space for it.
The bulk of the object does exist even before you declare the object.
Generally the actual code will be greater than the object itself (in size)
and all of the code exists and is ready to call before an instance is
created.
To say, "Look at the space for this object that I have not created yet and
tell me what it says" would naturally throw an error.
There is no reason calling a function on a null object *has* to raise an
exception, the designers of C# just designed it that way. They actually
needed to put an extra check in to stop it working. Basically when you call,
say, object.ToString you end up calling a global function ToString where the
pointer to the object is passed in, ie

x.ToString();

translates to (under the hood of course)

public static string ToString(object* pObject)
{
//convert pObject to sring
}

I'm sure it's more complicated than that but that's the basic idea. The
compiler does the null check before the static function is called but there
is no reason that it needs to. It can easily call the static ToString
function and let that function decide whether to allow nulls or not.

Michael
Aug 28 '08 #4
"Alberto Poblacion" <ea******************************@poblacion.orgwro te
in message news:e8**************@TK2MSFTNGP06.phx.gbl...
No, not really. You can do that with extension methods (as you already
point out at the end of your message), but the real ToString is not
static; it is a virtual method that can be overridden in child classes:
Technically the real ToString is not static, it's global. But as C# doesn't
have global functions I wrote it as static.
class Object
{
public virtual string ToString()
{
return this.GetType().Name;
}
}

This can't work if the object is null.
Yes it can because the type tells you whether to call the original ToString
or the overridden ToString, eg

object x = null;
x.ToString(); //<-- calls the ToString defined by object

MyClass x = null;
x.ToString(); //<-- calls the ToString override on MyClass

being that the real to string function looks like this:

public static String ToString(MyClass* Value)
{
}

Then it is possible to call on a null reference becase null can be passed in
to the Value parameter.

Michael
Aug 28 '08 #5
On Wed, 27 Aug 2008 19:27:45 -0700, Michael C <mi***@nospam.comwrote:
"Alberto Poblacion" <ea******************************@poblacion.org>
wrote
in message news:e8**************@TK2MSFTNGP06.phx.gbl...
> No, not really. You can do that with extension methods (as you already
point out at the end of your message), but the real ToString is not
static; it is a virtual method that can be overridden in child classes:

Technically the real ToString is not static, it's global. But as C#
doesn't
have global functions I wrote it as static.
No, Object.ToString() is not static, and it's not global. It's a virtual
instance method in the Object class. Every type inherits Object and so
every object has the ToString() method. You are right that C# doesn't
have global functions, and that includes even Object.ToString().
>class Object
{
public virtual string ToString()
{
return this.GetType().Name;
}
}

This can't work if the object is null.

Yes it can because the type tells you whether to call the original
ToString
or the overridden ToString, eg
No, it can't. You cannot use any instance member of a class with a null
reference. In the case of ToString(), it's particularly problematic
because it's a virtual method and you need an instance to get at the
v-table. But even for non-virtual members the run-time requires an actual
instance.

In C++, for a non-virtual member, you could actually call the member with
a null reference. But even in C++ you can't call a virtual function with
a null reference. There's just no way that what you'd want to work could
work, because ToString() is virtual.
object x = null;
x.ToString(); //<-- calls the ToString defined by object
See above. It just can't work.
MyClass x = null;
x.ToString(); //<-- calls the ToString override on MyClass
See above. This _definitely_ can't work. Overrides are handled via a
v-table that is referenced from the object instance. No object instance,
no v-table, no way to call the method. There'd be no way for the run-time
to distinguish which version of the ToString() method should be called,
because static typing has nothing to do with choosing the implementation
for virtual methods.

For example, given that:

String x = "5";
Object obj = x;

obj.ToString();

winds up calling the String.ToString() implementation, what should happen
if you have:

String x = null;
Object obj = x;

obj.ToString();

To be consistent, it should call String.ToString(). But how is it to know
that should happen?
being that the real to string function looks like this:

public static String ToString(MyClass* Value)
{
}
The real ToString() method doesn't look anything like that.

Pete
Aug 28 '08 #6
On Wed, 27 Aug 2008 19:20:11 -0700, Michael C <mi***@nospam.comwrote:
[...]
There is no reason calling a function on a null object *has* to raise an
exception,
That's only partly true. For virtual methods, it _does_ have to raise an
exception.
the designers of C# just designed it that way.
I believe that this is a run-time rule. You can't call an instance method
on a null reference in C++/CLI either.
They actually
needed to put an extra check in to stop it working. Basically when you
call,
say, object.ToString you end up calling a global function ToString where
the
pointer to the object is passed in,
That's just not true.
[...]
I'm sure it's more complicated than that but that's the basic idea. The
compiler does the null check before the static function is called
There's no static function, and it's not the compiler generating the code
to do the check. It's part of the run-time.
but there
is no reason that it needs to. It can easily call the static ToString
function and let that function decide whether to allow nulls or not.
No, it can't.

Pete
Aug 28 '08 #7
"Peter Duniho" <Np*********@nnowslpianmk.comwrote in message
news:op***************@petes-computer.local...
No, Object.ToString() is not static, and it's not global.
I'm loathe to reply to you peter as I find you can be quite rude (and
usually very negative and unpleasant) but here goes for now.

Actually that is wrong, every function under the hood is global. It has a
location in memory and any code in the current process can call that
function. The C# IDE tricks us into thinking it's instance or static or
private or whatever.
It's a virtual instance method in the Object class. Every type inherits
Object and so every object has the ToString() method. You are right that
C# doesn't have global functions, and that includes even
Object.ToString().
I'm talking about under the hood at the assembly level.
No, it can't. You cannot use any instance member of a class with a null
reference. In the case of ToString(), it's particularly problematic
because it's a virtual method and you need an instance to get at the
v-table. But even for non-virtual members the run-time requires an actual
instance.
There is no reason this can't be worked around.
For example, given that:

String x = "5";
Object obj = x;

obj.ToString();

winds up calling the String.ToString() implementation, what should happen
if you have:

String x = null;
Object obj = x;

obj.ToString();
Simple, it calls the Object.ToString.
To be consistent, it should call String.ToString(). But how is it to know
that should happen?
Obviously it should call Object.ToString.
>being that the real to string function looks like this:

public static String ToString(MyClass* Value)
{
}

The real ToString() method doesn't look anything like that.
Really? What does it look like then peter?

Michael
Aug 28 '08 #8
"Peter Duniho" <Np*********@nnowslpianmk.comwrote in message
news:op***************@petes-computer.local...
That's only partly true. For virtual methods, it _does_ have to raise an
exception.
No, it can do whatever the designers decide it can do. They could have
called the ToString method if they had wanted to. Possibly there are
disadvantages but say it is not possible is just plain wrong.
That's just not true.
Oh yes it is (see, I can disagree with no detail too :-)
There's no static function,
Static was not the best choice of words but I've already explained why I
used that term. I'd repeat my explanation but it appears you've missed it a
couple of times already.
and it's not the compiler generating the code to do the check. It's part
of the run-time.
Big deal, there's still a compiler and the compiler could do whatever the
designers want.
No, it can't.
Oh yes it can stoopid.

>
Pete

Aug 28 '08 #9
On Wed, 27 Aug 2008 23:04:23 -0700, Michael C <mi***@nospam.comwrote:
"Peter Duniho" <Np*********@nnowslpianmk.comwrote in message
news:op***************@petes-computer.local...
>That's only partly true. For virtual methods, it _does_ have to raise
an
exception.

No, it can do whatever the designers decide it can do.
You should probably learn a little more about virtual methods (functions)
(particularly as they are implemented in langauges like C++, C#, VB.NET
and Java) before you make any more claims like that. Here's a decent
place to start:
http://en.wikipedia.org/wiki/Virtual_table
They could have
called the ToString method if they had wanted to. Possibly there are
disadvantages but say it is not possible is just plain wrong.
No, it's exactly right. By definition, a virtual method needs an
instance. The run-time can't just go picking arbitrary methods to call
when there's a null reference, and the compiler doesn't emit enough
information for the run-time to know what the static typing of the
variable was.
[...]
Oh yes it can stoopid.
Ah, right. I forgot that when you run out of words, you start calling
people names. That really helps you look credible.

Pete
Aug 28 '08 #10
"Peter Duniho" <Np*********@nnowslpianmk.comwrote in message
news:op***************@petes-computer.local...
You should probably learn a little more about virtual methods (functions)
(particularly as they are implemented in langauges like C++, C#, VB.NET
and Java) before you make any more claims like that. Here's a decent
place to start:
http://en.wikipedia.org/wiki/Virtual_table
I know how virtual methods work.
No, it's exactly right. By definition, a virtual method needs an
instance. The run-time can't just go picking arbitrary methods to call
when there's a null reference, and the compiler doesn't emit enough
information for the run-time to know what the static typing of the
variable was.
For a null value they can whatever they (MS) like. They could have made it
work like an extension method. The funny thing I find is that you bring up a
load of crap that makes no sense and ignore the one big arguement I was
expecting. Basically implementing this feature would require every
underlying method to check for null which would be a big overhead when this
feature wouldn't be used all that often.
>
>[...]
Oh yes it can stoopid.

Ah, right. I forgot that when you run out of words, you start calling
people names. That really helps you look credible.
You really don't have a clue how you come across do you peter? From your
previous posts I have absolutely zero respect for you. Your rather subtle in
attempting to belittle those you speak to when it comes to the crunch you
can claim ignorance. Take your very first response to this post above
suggesting I read wiki. This is a subtle way of saying "you're stupid" but
something you fully intended and something you do in most of your posts.
Perhaps you should go learn some people skills.

Michael
Aug 28 '08 #11
Dang guys! Be nice! Christmas is right around the corner and we all want him
to bring us more RAM and a Service Pack, don't we?

;)

"Michael C" wrote:
"Peter Duniho" <Np*********@nnowslpianmk.comwrote in message
news:op***************@petes-computer.local...
You should probably learn a little more about virtual methods (functions)
(particularly as they are implemented in langauges like C++, C#, VB.NET
and Java) before you make any more claims like that. Here's a decent
place to start:
http://en.wikipedia.org/wiki/Virtual_table

I know how virtual methods work.
No, it's exactly right. By definition, a virtual method needs an
instance. The run-time can't just go picking arbitrary methods to call
when there's a null reference, and the compiler doesn't emit enough
information for the run-time to know what the static typing of the
variable was.

For a null value they can whatever they (MS) like. They could have made it
work like an extension method. The funny thing I find is that you bring up a
load of crap that makes no sense and ignore the one big arguement I was
expecting. Basically implementing this feature would require every
underlying method to check for null which would be a big overhead when this
feature wouldn't be used all that often.
[...]
Oh yes it can stoopid.
Ah, right. I forgot that when you run out of words, you start calling
people names. That really helps you look credible.

You really don't have a clue how you come across do you peter? From your
previous posts I have absolutely zero respect for you. Your rather subtle in
attempting to belittle those you speak to when it comes to the crunch you
can claim ignorance. Take your very first response to this post above
suggesting I read wiki. This is a subtle way of saying "you're stupid" but
something you fully intended and something you do in most of your posts.
Perhaps you should go learn some people skills.

Michael
Aug 28 '08 #12
On Thu, 28 Aug 2008 01:10:02 -0700, Michael C <mi***@nospam.comwrote:
[...]
>Even more generally, you simply cannot call a virtual method without an
instance. You couldn't even do what you're talking about in plain,
unmanaged C++. If you still think you can call a virtual method without
an instance, I encourage you to post the C++ code that would do so.

If MS wanted to do it they could. They could just use the VTable for the
type.
And where would they get the v-table? If it's to work without an actual
instance, it would have to come from the static typing. And if the
compiler is using the static typing to obtain the v-table, what's the
point of having a v-table at all?

You can write the word "rubbish" as many times as you like. It doesn't
actually _demonstrate_ anything except your lack of understanding about
how virtual method calls work.
[...]
>Alberto already posted it. Was there something about that you had
trouble
understanding?

I didn't think you would be able to answer than one.
Try me. If you didn't understand Alberto's post, I'm happy to try to
help. But you have to ask the question first. There's no point in me
just copying and pasting what he posted, given that you failed to
understand it the first time. You need to elaborate on what it was that
confused you.

All that said, the real issue here is that the .NET designers decided to
not allow null "this" references for _any_ instance member. You'd have to
ask them if you want their exact reasons, but the fact is that null "this"
references causes bugs in more situations than in which it's helpful.
It's extremely useful for an instance member to be able to assume that
"this" is non-null, and so that's the rule .NET imposes.

In your specific example, it wouldn't even be possible. It's unfortunate
that you don't understand why. But in the end, it's a moot point: even
for non-virtual members, there's a reason for why a null "this" reference
isn't allowed.

Pete
Aug 28 '08 #13
On Thu, 28 Aug 2008 01:17:30 -0700, Michael C <mi***@nospam.comwrote:
"Peter Duniho" <Np*********@nnowslpianmk.comwrote in message
news:op***************@petes-computer.local...
>You should probably learn a little more about virtual methods
(functions)
(particularly as they are implemented in langauges like C++, C#, VB.NET
and Java) before you make any more claims like that. Here's a decent
place to start:
http://en.wikipedia.org/wiki/Virtual_table

I know how virtual methods work.
Be that as it may, you haven't been demonstrating that here.
[...]
>>[...]
Oh yes it can stoopid.

Ah, right. I forgot that when you run out of words, you start calling
people names. That really helps you look credible.

You really don't have a clue how you come across do you peter?
This coming from the person who resorts to name-calling?
From your
previous posts I have absolutely zero respect for you.
Frankly, you seem to have zero respect for anyone. Why should I be
concerned about whether you have respect for me?
Your rather subtle in
attempting to belittle those you speak to when it comes to the crunch you
can claim ignorance.
That's not even a grammatically valid sentence. But regardless, if I'm so
"subtle" in "attempting to belittle", what makes you think you can make
the claim that that's even what I'm doing?

If you feel belittled, it's simply because you wrote something wrong that
needed correcting, but can't deal with it. I certainly didn't set out
with the intention to make you feel belittled.
Take your very first response to this post above
suggesting I read wiki. This is a subtle way of saying "you're stupid"
It's a not-so-subtle way of saying "you should learn about this first".
That's hardly the same thing as calling you "stupid".
but
something you fully intended and something you do in most of your posts.
Perhaps you should go learn some people skills.
I have people skills. They just don't involve candy-coating corrections
for people who are more interested in causing a ruckus and insulting
others than in learning something new. You need to get used to the idea
that it's possible for you to be wrong and for someone to point that out
without it reflecting poorly on you at all, never mind be a case of that
someone "belittling" you.

Everyone's wrong some times. It's how one deals with being wrong that
defines what kind of person they are. So far, you're not doing so well.

When you've figured all that out, you'll find yourself getting offended
much less often. In the meantime, I think about as much actual
information has been presented in this thread as could be. I've explained
the errors in your assertions and the design more generally. You can
continue the pissing match on your own if you like.

Pete
Aug 28 '08 #14
Michael C wrote:
"jp2msft" <jp*****@discussions.microsoft.comwrote in message
news:8D**********************************@microsof t.com...
>Even if you declare an object, it doesn't really exist yet until you
have initialized it and the compiler has not set aside any space for
it.

The bulk of the object does exist even before you declare the object.
Generally the actual code will be greater than the object itself (in
size) and all of the code exists and is ready to call before an
instance is created.
>To say, "Look at the space for this object that I have not created
yet and tell me what it says" would naturally throw an error.

There is no reason calling a function on a null object *has* to raise
an exception, the designers of C# just designed it that way. They
actually needed to put an extra check in to stop it working.
Basically when you call, say, object.ToString you end up calling a
global function ToString where the pointer to the object is passed
in, ie
x.ToString();

translates to (under the hood of course)

public static string ToString(object* pObject)
{
//convert pObject to sring
}

I'm sure it's more complicated than that but that's the basic idea.
No, it's not really even all that close. And the devil is in the details.

The actual call x.ToString(), being virtual, ends up looking like it was
generated by something like this:

(*g_types[x->typetag].Methods['ToString'])(x);

unless the JIT hasn't compiled the MSIL into machine language yet, in which
case it does that before calling the function.

The actual function called depends on the actual run-time type of the
instance passed in. The run-time type is encoded in the first four bytes
(on x86) of each ref-typed object instance. The first four bytes of the
object instance referred to by null.... do you see the problem now? No
instance implies no type tag which implies no way to select the "right"
ToString implementation.
The compiler does the null check before the static function is called
but there is no reason that it needs to. It can easily call the
static ToString function and let that function decide whether to
allow nulls or not.
Michael

Aug 28 '08 #15
Oh, and just for grins, I can provide example code where x == null but
x.ToString() succeeds. Hint: !object.ReferenceEquals(x, null)
Aug 28 '08 #16
On Aug 28, 6:58*am, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:
the designers of C# just designed it that way.

I believe that this is a run-time rule. *You can't call an instance method *
on a null reference in C++/CLI either.
Not quite. The CLR allows one to call instance methods on null
receivers, so long as the call is not virtual (IL opcode "call" as
opposed to "callvirt"). The design decision for both C# and C++/CLI
was to use "callvirt" throughout, even for non-virtual methods,
precisely because it always does the null-check. But you can always
write your own IL which uses "call". Or you can use one of those
Delegate.CreateDelegate overloads which take an instance method and
expose its receiver as an explicit argument on the delegate, and then
pass null to that, in C# as well as any other .NET language

Of course, Object.ToString is virtual, so none of the above applies to
it.
Aug 31 '08 #17
On Aug 27, 12:15*pm, "Michael C" <mi...@nospam.comwrote:
If we have something like this

object x = null;
MessageBox.Show(x.ToString())

we get an error. That kindof makes sense but there is no reason the
behaviour couldn't be to return an empty string.
Of all object-oriented languages with single dispatch I know of, the
only one which explicitly permitted null receivers for non-virtual
methods was Delphi. Even in C++, calling a non-virtual method on a
null pointer is U.B. (it _usually_ works on a typical implementation,
but relying on that is not a good idea). Why should C# be any
different?

By the way, RemObjects Oxygene has what you want, though it works in a
slightly different way - they have a colon-operator for method calls,
which works the same as dot, except that it returns null if the
receiver is null - i.e., for o==null, o.ToString is still an
exception, but o:ToString is null. The convenience of defining it thus
is that you can chain it - a:b:c:ToString - and know that you'll get
null if any of the subexpressions in the call chain yield null. This
is often handy when working with deep object graphs, XPath-style, and
would be convenient to have in C#. But it's still rather different
from what you propose.
Aug 31 '08 #18
"Pavel Minaev" <in****@gmail.comwrote in message
news:02**********************************@m44g2000 hsc.googlegroups.com...
This
is often handy when working with deep object graphs, XPath-style, and
would be convenient to have in C#. But it's still rather different
from what you propose.
Thanks for the reply. I think extension methods do what I want so something
built into the language specifically for this probably wouldn't be much
advantage. I'm not sure if it would replace your example of a:b:c etc but
for simple stuff like ToString it works quite well.

Michael
Aug 31 '08 #19
On Aug 31, 5:51*am, "Michael C" <m...@nospam.comwrote:
"Pavel Minaev" <int...@gmail.comwrote in message

news:02**********************************@m44g2000 hsc.googlegroups.com...
This
is often handy when working with deep object graphs, XPath-style, and
would be convenient to have in C#. But it's still rather different
from what you propose.

Thanks for the reply. I think extension methods do what I want so something
built into the language specifically for this probably wouldn't be much
advantage. I'm not sure if it would replace your example of a:b:c etc but
for simple stuff like ToString it works quite well.

Michael

Quite a talk here!

Commenting on the original post, letting it slide and not throw the
error (yes, it can't be done because of the missing instance, the
vtable and the rest ot the Universe, and yes, Thee C# One could have
wired the runtime/compiler to let it slide) feels to me a bit like
option explicitless VB.
After all, doesn't it all boil down to being bug-free when x is null?
anyway... keep using up the Bandwidth. Young people need this kinda
talk otherwise they'll think the virtual table is a table with no
legs.

Aug 31 '08 #20

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

13 posts views Thread by Jason Huang | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.