Le eccezioni NullReference sono uno degli incubi ricorrenti degli sviluppatori, C# e non, soprattutto alle prime armi o poco attenti.
L'operatore null-conditional, chiamato anche di null-propagation, introdotto da C# 6 consente di gestire varie situazioni in cui si rende necessario controllare il fatto che un oggetto sia null, ed evitare di incorrere nelle comuni NullReferenceException, riducendo la quantità di codice ripetitivo da scrivere.
L'operatore ? permette di accedere a membri ed indicizzatori di un oggetto solamente quando l'oggetto stesso non è null, restituendo in caso contrario il valore null.
Supponiamo ad esempio di avere una classe Persona così fatta:

class Persona
{
     public string Nome{get;set;}
     public Indirizzo IndirizzoPersona{get;set;}
}

Supponiamo di voler ricavare il Nome da un'istanza p della classe e memorizzarlo in una variabile. La prima cosa di cui essere sicuri è che l'istanza stessa sia diversa da null:

string nome=null;
if(p!=null)
    nome=p.Nome;

Il primo utilizzo dell'operatore null conditional, permette di evitare l'if/else:

string nome=p?.Nome;

In tal modo, se p è null, la variabile nome assumerebbe valore null, altrimenti il valore della proprietà Nome.
L'operatore è utilizzabile in maniera molto proficua in congiunzione con l'operatore ?? di null coalescing.
Se volessimo infatti assegnare un valore diverso da null alla variabile nome, potremo scrivere:

string nome=p?.Nome ?? "senza nome"; //se p è null restituisce "senza nome"

Così, se p è null, l'operatore null conditional restituirà valore null, e quindio l'operatore ?? a sua volta restituirà il secondo operando "senzanome".
L'operatore null-conditional è utilizzabile anche con membri indicizzatori, per esempio, supponiamo di voler ricavare il primo carattere del nome dell'istanza p.
Se p è null, l'operatore restituisce null, in caso contrario potrà accedere all'indice zero:

char? primo=p?[0];

Una delle caratteristiche dell'operatore null conditional, per cui viene chiamato anche operatore di null propagation, permette di sfruttare un comportamento di corto circuito, concatenando l'utilizzo dello stesso, accedendo a membri di un oggetto e quindi a relativi sottomembri.
Supponiamo che la classe Indirizzo, usata all'interno di Persona sia fatta così:

class Indirizzo
{
   public string Via {get;set;}
   public int Numero {get;set;}
   public Comune Citta {get;set;}
}
 
class Comune
{
   public string Nome{get;set;}
   public string Provincia {get;set;}
}

La classe Indirizzo a sua volta espone una proprietà di classe Comune.
Se volessimo ricavare il nome della Provincia in cui vive una Persona, dovremmo effettuare un controllo in cascata per evitare null-reference sui vari membri:

Person p=...;
string prov;
if(p.Indirizzo!=null)
{
    if(p.Indirizzo.Citta!=null)
       prov=p.Indirizzo.Citta.Provincia;
}
else prov="non impostato";

con l'operatore di null propagation si può scrivere tutto su una riga:

string prov=p.Indirizzo?.Citta?.Provincia ?? "non impostato";

Anche questa volta abbiamo usato l'operatore ?? per restituire un valore di default, diverso da null.

Un uso dell'operatore che sicuramente diverrà pratica comune è quello che, con un evento, anzichè verificare manualmente che ci sia un gestore e quindi invocarlo, come nel seguente esempio:

public event EventHandler NomeChanged;
 
private string _nome;
 
public string Nome
{
    get { return _nome; }
    set {
        if(_nome!=value)
        {
             _nome = value;
             if (NomeChanged != null)
               NomeChanged(this, null);
        }
    }
}

ci permetterà di scrivere al posto dell'ultimo if:

NomeChanged?.Invoke(this, args);

In attesa del rilascio definitivo di C# 6, potete provare queste e altre nuove funzionalità (oggetto magari di prossimi post) con la versione preview di Visual Studio 2015, che trovate al seguente link:
http://www.visualstudio.com/en-us/downloads/visual-studio-2015-downloads-vs.aspx