Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why null statement ToString() returns an empty string? [duplicate]

Tags:

c#

nullable

I am just wondering what is the difference between the two next statements:

  1. Causes a NullReferenceException - it is OK.

    object test1 = default(int?);
    object result = test1.ToString();
    
  2. Returns an empty string "", why?

    object test2 = default(int?).ToString();
    
  3. This is same as 2.

    int? test3 = null;
    if (test3.ToString() == string.Empty) //returns true
    {
        Console.WriteLine("int? = String.Empty, isn't it strange?").
    }
    
  4. And just for fun - I can prove that bool can be equal to int value (hmmm how? bool can be only false, or true and int never can be that).

    if (default(int?).ToString() == default(bool?).ToString()) //returns true because both are empty strings
    {
        Console.WriteLine("int = bool");
    }
    

Note: default(int?) returns null.

like image 318
Misha Zaslavsky Avatar asked Oct 18 '13 17:10

Misha Zaslavsky


People also ask

What does ToString return for null?

Returns: a string representation of the object. In other words null is not a defined return value. If you don't override the toString() method then you will always get a string that at least gives you the Object's ID.

When string is empty it returns empty string?

An empty string is a string instance of zero length, whereas a null string has no value at all. An empty string is represented as "" . It is a character sequence of zero characters. A null string is represented by null .

Is it better to use null or empty string in Java?

So, NULL is better. An empty string is useful when the data comes from multiple resources. NULL is used when some fields are optional, and the data is unknown.

How do you create an empty string to null in Java?

str = str. replace(null,""); As String is immutable in java, you need to assign the result either to new String or same String. String's replace() method returns a string replacing all the CharSequence to CharSequence.


2 Answers

An int? is a Nullable<int>. Nullable is a struct, which makes it a value type, not a reference type. test3 isn't actually set to null. Assigning null to it actually results in the creation of a new structure that simply has the HasValue field of that struct set to false instead of true. (Special compiler support is required for such an implicit conversion to take place; so you couldn't have your own MyNullable<T> type that did this.)

Since the nullable object has an actual value, it can call ToString and provide a meaningful value, in this case, an empty string.

When you box that nullable value by putting it in an object variable it will result in an actual null value being stored in that variable, which is why you get a NRE when calling a method on it.

When a nullable value type is boxed it doesn't box the nullable value type; instead if it has no value it assigns null to the object, if it has a value then that underlying value is unwrapped and then boxed. (Special support from the runtime is required for this behavior, which is another reason why you can't make your own MyNullable<T> type.)

like image 185
Servy Avatar answered Sep 25 '22 21:09

Servy


In C, one uses the token . to access a member of the left operand, and -> to access a member of the thing to which the left operand holds a pointer (reference). A null reference occurs if the left-hand operand of -> is null. In C#, the . has the former meaning when applied to value types and the latter meaning when applied to class types; using . in C# on a class type variable which is null will trigger a NullReferenceException.

The .NET type Nullable<T> is a two-field structure which contains Boolean field which indicates whether it has a meaningful (non-null) value, and field of value type T to say what that value is (if not null). Although the compiler will allow one to assign a Nullable<T> to null or compare one with null, the null in the former case is really just shorthand for a default instance (where the "has-value" flag is false, and the value field holds the default value for type T), and the comparison to null is really just a shorthand for checking the HasValue property (which in turn looks at the Boolean field). Invoking ToString on e.g. a Nullable<int> which is "null" is no different semantically from invoking it on any other structure that contains a Boolean and an Int32 which have the values False and 0, respectively. There are a few ways in which compilers treat nullable types "specially", but a default-valued Nullable<int> holds [False, 0], not a null reference.

Note that the first example throws because of one of the "special" rules the framework applies to nullable types. Casting a value type to Object or another reference type generally instructs the runtime to create an object that will behave as a class object with fields and members matching those of the struct and return a reference to that new object--a process known as "boxing". Because the designers of nullable types wanted to allow code to say if (NullableThing == null) rather than the (IMHO sematically clearer) if (!NullableThing.HasValue), the runtime was implemented so that boxing a nullable whose HasValue field is false will yield a null reference rather than a reference to a default-valued instance of Nullable<T>. While I think there are cases where would make sense to have some value types use different box and unbox methods, nullable types are the only ones that can use anything other than normal boxing.

like image 31
supercat Avatar answered Sep 24 '22 21:09

supercat