C#
null handling
Convert.ToString
type casting
programming concepts

Why does Convert.ToStringnull return a different value if you cast null?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Convert.ToString(null) in C# can produce different results depending on how null is typed at compile time. The key reason is overload resolution: the compiler chooses a method signature before runtime. Casting null changes which overload is selected, and each overload can define different behavior.

Overload Resolution Explains the Difference

Convert.ToString has many overloads, including ToString(object value) and ToString(string value). A plain null literal can match multiple candidates, and the best match is selected by compiler rules.

csharp
1using System;
2
3public class Demo
4{
5    public static void Main()
6    {
7        string a = Convert.ToString(null);
8        string b = Convert.ToString((object)null);
9        string c = Convert.ToString((string)null);
10
11        Console.WriteLine(a == null ? "a is null" : $"a='{a}'");
12        Console.WriteLine(b == null ? "b is null" : $"b='{b}'");
13        Console.WriteLine(c == null ? "c is null" : $"c='{c}'");
14    }
15}

On modern runtimes, all three often become empty string, but behavior can vary by framework version and specific API overloads in other classes. The important point is that cast type controls selected method.

Compare with Instance ToString

A separate issue is calling .ToString() on a null reference, which throws NullReferenceException. Convert.ToString is designed to be null-safe; instance ToString is not.

csharp
1using System;
2
3public class Compare
4{
5    public static void Main()
6    {
7        object x = null;
8
9        Console.WriteLine(Convert.ToString(x) == "" ? "empty" : "value");
10
11        try
12        {
13            Console.WriteLine(x.ToString());
14        }
15        catch (NullReferenceException)
16        {
17            Console.WriteLine("instance ToString on null throws");
18        }
19    }
20}

This distinction explains many production bugs where null handling seems inconsistent.

Practical Guidelines for Null-safe String Conversion

If you want explicit behavior, do not rely on overload subtleties. Choose a clear strategy and encode it directly.

csharp
1using System;
2
3public static class SafeText
4{
5    public static string NullAsEmpty(object value)
6    {
7        return value == null ? "" : value.ToString();
8    }
9
10    public static string NullAsLiteral(object value)
11    {
12        return value == null ? "null" : value.ToString();
13    }
14}

These helpers document intent and reduce ambiguity during refactoring.

When reviewing code, also watch for interpolation and concatenation behavior. String interpolation can format null values differently than custom conversion helpers, so consistency checks matter in logging pipelines.

How to Make Behavior Explicit in APIs

When public methods accept optional values, define conversion policy in one layer and avoid repeated inline conversions. This makes tests straightforward and prevents accidental behavior drift when overloads or nullable types change.

csharp
1using System;
2
3public enum NullStringPolicy
4{
5    Empty,
6    LiteralNull
7}
8
9public static class Formatter
10{
11    public static string ToText(object value, NullStringPolicy policy)
12    {
13        if (value == null)
14        {
15            return policy == NullStringPolicy.Empty ? "" : "null";
16        }
17        return value.ToString();
18    }
19}
20
21public class Program
22{
23    public static void Main()
24    {
25        Console.WriteLine($"[{Formatter.ToText(null, NullStringPolicy.Empty)}]");
26        Console.WriteLine($"[{Formatter.ToText(null, NullStringPolicy.LiteralNull)}]");
27    }
28}

By centralizing formatting decisions, you avoid subtle overload surprises and keep log output consistent across services.

Unit tests should assert expected outputs for null, empty string, and whitespace separately. Many systems treat these values differently in downstream storage and analytics. If you define conversion policy once and test it, future framework upgrades are less likely to introduce subtle reporting bugs.

If your API surface includes nullable reference types, annotate method contracts clearly and keep conversion decisions close to boundary layers. This prevents accidental differences between internal objects and serialized output. Consistency at boundaries reduces support incidents and simplifies cross-service debugging.

Small conversion helpers also improve code reviews because intent is explicit and repeatable.

Common Pitfalls

  • Assuming all null inputs call the same overload regardless of cast type.
  • Confusing Convert.ToString(value) with value.ToString() on nullable references.
  • Depending on implicit runtime behavior instead of defining explicit null policy.
  • Mixing different null-to-string conventions across modules and logs.
  • Ignoring framework version differences when reproducing historical behavior.

Summary

  • Casting null changes overload resolution at compile time.
  • Convert.ToString and instance .ToString() have different null behavior.
  • Write explicit helper methods when null formatting must be predictable.
  • Keep a single null-string policy across your codebase.
  • Test conversion behavior in the exact runtime version you deploy.

Course illustration
Course illustration

All Rights Reserved.