C# approach to prevent null references in strings My insight here is that it's usually not useful to distinguish between null and empty strings. Sometimes it is, but usually not. Usually I like to assign my strings as empty if they would have been null.

var lastName = Request.Params["lastName"] ?? ""

Thus I had the idea of a struct which would wrap a real string, internally coalesce it to "", prevent all manner of null references, provide "less dangerous" versions of common string operations, yet still be compatible with strings. 

This is an incomplete listing--I just wanted to get feedback on the idea. Please let me know why this is awesome, mediocre, or just plain terrible!

//with normal string
public void WriteName(string name)
{
    if(name != null &amp;&amp; name.Length &gt; 30)
    { name = name.Substring(0,30); }

    Console.WriteLine(name);
}




//with safestring
public void WriteName(SafeString name)
{
    Console.WriteLine(name.ReduceTo(30));
}


Below is the SafeString struct:

/// &lt;summary&gt;
/// Struct wrapper for a string, to prevent null references when you 
///  don't care to distinguish between `null` and empty strings.
/// Has implicit conversions to &amp; from string
/// &lt;/summary&gt;
public struct SafeString : IEquatable&lt;SafeString&gt;, IEquatable&lt;string&gt;
{
    /*
      The wrapped string value. 
      This will be properly initialized only if the constructor is called.
      It's possible to create a struct with `default(SafeString)` 
        or by calling the parameterless ctor, `new SafeString()`
      C#6 will allow us to define a parameterless ctor, 
        but there is still the issue of `default(SafeString)` which does not call any ctor.
      Thus when we wish to use the value of `_theString`, 
        we need to either to check for null or funnel access through a helper        
    */
    private string _theString;

    public SafeString(string s)
    {
        _theString = s ?? "";
    }

    public override string ToString()
    {
        //perform initialization in case this was created without using the ctor
        return _theString ?? (_theString = "");
    }

    public int Length { get { return ToString().Length; } }


    //safe substring method -- so you don't get an error when asking for a substring 
    //   longer than the original
    public SafeString SubString(int start, int length)
    {
        if (start &lt; 0)
        {
            start = 0;
        }
        if (length &lt;= 0)
        {
            return "";
        }

        var over = Math.Max((start + length) - Length, 0);
        length = length - over;

        return ToString().Substring(start, length);
    }

    //shorthand for SubString(0,length), for when you wish to cut a string down to size
    public SafeString ReduceTo(int length)
    {
        if (length &gt; Length)
        {
            return this;
        }
        return SubString(0, length);
    }


    public bool IsEmpty { get { return string.IsNullOrEmpty(_theString); } }
    public bool IsWhitespace { get { return string.IsNullOrWhiteSpace(_theString); } }


    public static implicit operator string(SafeString ss)
    {
        return ss.ToString();
    }

    public static implicit operator SafeString(string s)
    {
        return new SafeString(s);
    }

    public override int GetHashCode()
    {
        return ToString().GetHashCode();
    }

    public override bool Equals(object obj)
    {            
        if (obj is SafeString)
        {
            return Equals((SafeString) obj);
        }
        if (obj is string)
        {
            return Equals((string) obj);
        }

        return false;
    }

    public bool Equals(SafeString other)
    {
        return ToString() == other.ToString();
    }

    public bool Equals(string other)
    {
        if (other == null)
        {
            return ToString() == ""; //we are never 'null'
        }
        return other == ToString();
    }
}
System.String is a class, a reference type. Wrapping it in a value type makes for a pretty confusing start: it's like the opposite of boxing, where a value type is wrapped with a reference type. It's ...awkward.

Value types should be immutable; _theString doesn't immediately strike me as a readonly field:


private string _theString;



And _theString is a very, very bad name - I would have simply gone with _value, like this:

private readonly string _value;


Calling ToString shouldn't have side-effects - here calling ToString is mutating the instance, changing the reference stored in _theString:


public override string ToString()
{
    //perform initialization in case this was created without using the ctor
    return _theString ?? (_theString = "");
}



There is little to no gain in doing this, and it makes your value type violate a fundamental rule: value types should be immutable, no ifs, no buts. I'd change it to this:

public override string ToString()
{
    return _value ?? string.Empty;
}


The only way client code can retrieve the encapsulated value, is by calling ToString - this is practical and useful, but not exactly instinctive. I would expose a getter:

public string Value { get { return ToString(); } }




The Equals(string) implementation relies on implementation details of another method:


return ToString() == "" //we are never 'null'



I don't see a need for an explanatory comment when using "normal" string methods:

return ToString().IsNullOrEmpty();




You have hard-coded "" in a bunch of places - I find string.Empty conveys "" in a more unambiguous way, and I would replace all occurrences of "" with string.Empty.



I think your struct is violating the Single Responsibility Principle, with methods like ReduceTo - I think these members belong as extension methods, extending the String type itself.

Also when writing code at that level, you should make sure every public member has proper XML comments, so that client code consuming it has a bit of documentation in IntelliSense.