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

This is a discussion on Why does x.ToString() throw an error if x == null? within the CSharp forums in Programming Languages category; 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 ...

Go Back   Application Development Forum > Programming Languages > CSharp

Object Mix

Register FAQ Calendar Search Today's Posts Mark Forums Read
  #1  
Old 08-27-2008, 04:15 AM
Michael C
Guest
 
Default 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





Reply With Quote
  #2  
Old 08-27-2008, 05:19 AM
Alberto Poblacion
Guest
 
Default Re: Why does x.ToString() throw an error if x == null?

"Michael C" <mikec@nospam.com> wrote in message
news:u7PSk0BCJHA.3392@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.



Reply With Quote
  #3  
Old 08-27-2008, 09:59 AM
jp2msft
Guest
 
Default RE: Why does x.ToString() throw an error if x == null?

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
>
>
>
>
>
>

Reply With Quote
  #4  
Old 08-27-2008, 10:20 PM
Michael C
Guest
 
Default Re: Why does x.ToString() throw an error if x == null?

"jp2msft" <jp2msft@discussions.microsoft.com> wrote in message
news:8D2A44C2-94FA-428F-A3A2-1F077B844B0D@microsoft.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


Reply With Quote
  #5  
Old 08-27-2008, 10:27 PM
Michael C
Guest
 
Default Re: Why does x.ToString() throw an error if x == null?

"Alberto Poblacion" <earthling-quitaestoparacontestar@poblacion.org> wrote
in message news:e8bnSYCCJHA.4368@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


Reply With Quote
  #6  
Old 08-27-2008, 10:53 PM
Peter Duniho
Guest
 
Default Re: Why does x.ToString() throw an error if x == null?

On Wed, 27 Aug 2008 19:27:45 -0700, Michael C <mikec@nospam.com> wrote:

> "Alberto Poblacion" <earthling-quitaestoparacontestar@poblacion.org>
> wrote
> in message news:e8bnSYCCJHA.4368@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
Reply With Quote
  #7  
Old 08-27-2008, 10:58 PM
Peter Duniho
Guest
 
Default Re: Why does x.ToString() throw an error if x == null?

On Wed, 27 Aug 2008 19:20:11 -0700, Michael C <mikec@nospam.com> wrote:

> [...]
> 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
Reply With Quote
  #8  
Old 08-28-2008, 01:59 AM
Michael C
Guest
 
Default Re: Why does x.ToString() throw an error if x == null?

"Peter Duniho" <NpOeStPeAdM@nnowslpianmk.com> wrote in message
newsp.ugksz6s58jd0ej@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


Reply With Quote
  #9  
Old 08-28-2008, 02:04 AM
Michael C
Guest
 
Default Re: Why does x.ToString() throw an error if x == null?

"Peter Duniho" <NpOeStPeAdM@nnowslpianmk.com> wrote in message
newsp.ugks72158jd0ej@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



Reply With Quote
  #10  
Old 08-28-2008, 02:30 AM
Peter Duniho
Guest
 
Default Re: Why does x.ToString() throw an error if x == null?

On Wed, 27 Aug 2008 22:59:54 -0700, Michael C <mikec@nospam.com> wrote:

> "Peter Duniho" <NpOeStPeAdM@nnowslpianmk.com> wrote in message
> newsp.ugksz6s58jd0ej@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.


You only find me "very negative and unpleasant" because you tend to post
things that don't make sense, which I then find myself correcting. It's
unfortunate that you don't handle disagreement and critique any better
than you do. Suffice to say, I don't go out of my way to upset you; you
just take it upon yourself to interpret things that way.

Witness the fact that in spite of me not writing anything significantly
different from what Alberto's written, you've already got that big chip
sitting up on your shoulder. You're just itching for a fight.

> Actually that is wrong, every function under the hood is global.


If that's true, then the term "global" is meaningless. If the word can't
be used to distinguish one kind of method from another, what's the point
of using it?

That said, using more widely accepted definitions of "global", it's not
true at all that "every function under the hood is global". The word
"global" refers to identifiers that require no qualification in order to
be resolved. It doesn't even make sense to talk about "global" with
respect to "under the hood", because "global" is an artifact of the
higher-level language being used.

In C#, there are no globals. Period. Everything requires qualification,
being contained at a minimum inside a class that's inside a namespace.

> 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.


No. If you were talking about C++, that would not be far from the truth.
But for managed code, the run-time is a lot more involved, while the C#
compiler leaves these things to the run-time. The C# compiler isn't
"tricking us" about anything.

>> 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.


I suggest you take a look at the code generated by the C# compiler. You
would find it educational.

>> 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.


In C#? Yes, there is. The C# compiler has no control over the rules the
run-time imposes.

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.

>> 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.


Um, no. That's far from obvious. Even aside from the inconsistency issue
I pointed out, the fact is that you need to decide when you design the
language: are you going to use static typing or polymorphism to decide
which method to call?

If you use static typing, then the compiler gets to decide which method to
call, and that has to be based on the type of the variable used. That
means that in the first example I gave, "obj.ToString()" is going to call
Object.ToString() even though the type of the instance is actually
String. Whether you like it or not, that's completely contrary to the
whole point of making ToString() virtual in the first place. Which means
that the language might as well not have virtual members.

Now, one can certainly design a language without virtual members. But
that's not C#, nor is it any other widely used OOP language. Virtual
members are a major component of what makes OOP so powerful.

So, maybe you decide you'd rather use polymorphism to decide which method
to call. That means that you need to look at the actual instance to
decide which method to call. But to do that, you need an instance and of
course instances exist only at run-time so the compiler cannot be involved
in making the decision at all.

So which is it going to be? Cripple the OOP language? Or disallow
calling of virtual methods with a null reference?

>>> 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?


Alberto already posted it. Was there something about that you had trouble
understanding?

Pete
Reply With Quote
Reply


Thread Tools
Display Modes


All times are GMT -5. The time now is 09:42 AM.


Powered by vBulletin® Version 3.7.2
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
vB Ad Management by =RedTyger=

In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.