Chiedere a un metodo generico di generare un tipo di eccezione specifico in caso di FAIL

StackOverflow https://stackoverflow.com/questions/41397

  •  09-06-2019
  •  | 
  •  

Domanda

Giusto, so che sembrerò totalmente un idiota con questo, ma il mio cervello è giusto non mettendosi in moto stamattina.

Voglio avere un metodo in cui posso dire "se va male, torna con questo tipo di eccezione", giusto?

Ad esempio, qualcosa come (e questo non funziona):

    static ExType TestException<ExType>(string message) where ExType:Exception
    {
        Exception ex1 = new Exception();
        ExType ex = new Exception(message);
        return ex;
    }

Ora ciò che mi confonde è che noi SAPERE che il tipo generico sarà di tipo Eccezione a causa di Dove clausola.Tuttavia, il codice fallisce perché non è possibile eseguire il cast implicito Eccezione A ExType.Non possiamo nemmeno convertirlo esplicitamente, come ad esempio:

    static ExType TestException<ExType>(string message) where ExType:Exception
    {
        Exception ex1 = new Exception();
        ExType ex = (ExType)(new Exception(message));
        return ex;
    }

Poiché anche questo fallisce..COSÌ è possibile una cosa del genere? Ho la forte sensazione che sarà davvero semplice, ma sto avendo una giornata dura con il vecchio, quindi datemi un po' di tregua :P


Aggiornamento

Grazie per le risposte ragazzi, sembra che non sia stato io a essere un completare idiota!;)

Ok allora Vegard E Sam mi ha portato al punto in cui potevo istanziare il tipo corretto, ma poi ovviamente mi sono bloccato perché the Messaggio param è di sola lettura dopo l'istanziazione.

opaco ha colpito nel segno con la sua risposta, l'ho testato e tutto funziona bene.Ecco il codice di esempio:

    static ExType TestException<ExType>(string message) where ExType:Exception, new ()
    {
        ExType ex = (ExType)Activator.CreateInstance(typeof(ExType), message);
        return ex;
    }

Dolce!:)

Grazie ragazzi!

È stato utile?

Soluzione

Puoi quasi farlo in questo modo:

static void TestException<E>(string message) where E : Exception, new()
{
    var e = new E();
    e.Message = message;
    throw e;
}

Tuttavia, ciò non viene compilato perché Exception.Message è di sola lettura.Può essere assegnato solo passandolo al costruttore e non c'è modo di vincolare un tipo generico con qualcosa di diverso da un costruttore predefinito.

Penso che dovresti usare la riflessione (Activator.CreateInstance) per "nuovare" il tipo di eccezione personalizzato con il parametro message, in questo modo:

static void TestException<E>(string message) where E : Exception
{
    throw Activator.CreateInstance(typeof(E), message) as E;
}

Modificare Oops ho appena capito che lo desideri ritorno l'eccezione, non buttarla.Si applica lo stesso principio, quindi lascerò la mia risposta così com'è con le dichiarazioni di lancio.

Altri suggerimenti

L'unico problema con la soluzione è che è possibile creare una sottoclasse di Exception che non implementa un costruttore con un singolo parametro di stringa, quindi potrebbe essere generata MethodMissingException.

static void TestException<E>(string message) where E : Exception, new()
{
    try 
    {
      return Activator.CreateInstance(typeof(E), message) as E;
    } 
    catch(MissingMethodException ex) 
    {
      return new E();
    }
}

Ho istanziato in linea il tipo di eccezione che voglio lanciare, in questo modo:

if (ItemNameIsValid(ItemName, out errorMessage))
    throw new KeyNotFoundException("Invalid name '" + ItemName + "': " + errorMessage);
if (null == MyArgument)
    throw new ArgumentNullException("MyArgument is null");

Hai provato, invece:

static T TestException<Exception>(string message)
{}

perché ho la sensazione che inserire il vincolo generico non sia necessario come tutte le eccezioni lanciabili dovere eredita comunque da System.Exception.

Ricorda che i generici accettano tipi ereditati.

Penso che visto che tutte le eccezioni dovrebbero avere un costruttore senza parametri e avere il file Message proprietà, quindi dovrebbe funzionare quanto segue:

static ExType TestException<ExType>(string message) where ExType:Exception
{
    ExType ex = new ExType();
    ex.Message = message;
    return ex;
}

Modificare:OK, Message è di sola lettura, quindi dovrai sperare che la classe implementi invece il costruttore Exception(string).

static ExType TestException<ExType>(string message) where ExType:Exception
{
    return new ExType(message);
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top