Lanciare un'eccezione all'interno di un costruttore di un'eccezione

4

Dato che stavo inserendo del codice TDD, mi è venuto in mente che una delle mie eccezioni digitate poteva potenzialmente generare NullReferenceException durante la creazione del suo messaggio di errore.

Ecco il costruttore per l'eccezione tipizzata in questione:

public class MyTypedException : Exception
{
  public MyTypedException(String expectedValue, ICollection<String> possibleValues)
  {
    String message = String.Format("Failed to find {0}.  Possible values:", expectedValue);
    foreach(var value in possibleValues)
    {
      message = String.Concat(message, ", ", value);
    }
    /* Assigns message to property, etc... */
  }
}

Se possibleValues è nullo, il costruttore di MyTypedException genererà un NullReferenceException . La mia prima reazione fu di pensare "Bene, controlla solo se possibleValues è nullo, e se lo è, lancia un ArgumentNullException . Tuttavia, lanciare un'eccezione diversa dal costruttore di un'escrizione sembra ... sbagliata.

L'alternativa sarebbe controllare se possibleValues è nullo o vuoto, e se lo è, crea un messaggio diverso, in questo modo:

public MyTypedException(String expectedValue, ICollection<String> possibleValues)
{
  String message = String.Empty;
  if (possibleValues == null || possibleValues.Count <= 0)
    message = "Failed to find {0} because the collection of possibles values is null or empty";
  else
  {
    message = String.Format("Failed to find {0}.  Possible values:", expectedValue);
    foreach (var value in possibleValues)
    {
      message = String.Concat(message, ", ", value);
    }
  }
  /* Assigns message to property, etc... */
}

È mai consentito lanciare un'eccezione diversa quando si tenta di creare un'eccezione?

    
posta CHendrix 07.03.2016 - 21:10
fonte

1 risposta

4

IMHO, è non OK .

Quando lanci un MyTypedException , l'aspetto più importante è che si è verificato un errore questo . Ovviamente gli errori secondari o gli errori di utilizzo potrebbero essere di interesse, ma sono secondari e il mascheramento di quello originale è una pessima idea.

Ovviamente, non è possibile evitare tutti gli errori (specialmente il citato OutOfMemory o simile), ma escludere errori fatali (come OOM, ecc.) consapevolmente lanciare qualcosa di diverso dall'eccezione prevista non mi sembra una buona idea.

Nota: nel tuo esempio, se ArgumentNullException indica un bug nel codice chiamante, allora altri mezzi per catturare il bug sono ovviamente una buona cosa:

  • Puoi Assert e poi
  • continua nel codice di produzione con la soluzione precedente
  • inoltre fai qualche registrazione di avviso / debug
  • e / o FailFast se pensi questo bug è fondamentale. (Non lo farei.)

Si noti inoltre che il ritardo di qualsiasi formattazione del messaggio in un secondo momento potrebbe anche avere senso (è sufficiente mantenere un riferimento agli argomenti passati e formattare su richiesta).

Non (manualmente) formattando affatto , quindi evitando l'intero problema di l'esempio potrebbe anche essere migliore.

    
risposta data 11.04.2016 - 16:59
fonte

Leggi altre domande sui tag