Domanda

.NET On-the-Fly compilatore per lo scripting CLR e vogliono metodo di esecuzione rendono accettabile generica :

object Execute()
{
  return type.InvokeMember(..);
}

T Execute<T>()
{
  return Execute() as T; /* doesn't work:
  The type parameter 'T' cannot be used with the 'as' operator because
  it does not have a class type constraint nor a 'class' constraint */

  // also neither typeof(T) not T.GetType(), so on are possible

  return (T) Execute(); // ok
}

Ma penso operatore as sarà molto utile: se il tipo di risultato non è il metodo T tornerà null, invece di un'eccezione! E 'possibile fare?

È stato utile?

Soluzione

È necessario aggiungere

where T : class

per il vostro dichiarazione di metodo, per es.

T Execute<T>()  where T : class
{

Tra l'altro, come un suggerimento, che wrapper generico in realtà non aggiunge molto valore. Il chiamante può scrivere:

MyClass c = whatever.Execute() as MyClass;

In alternativa, se vogliono gettare su fallire:

MyClass c = (MyClass)whatever.Execute();

Il metodo wrapper generico simile a questo:

MyClass c = whatever.Execute<MyClass>();

Tutte e tre le versioni hanno di specificare esattamente le stesse tre entità, solo in ordine diverso, in modo che nessuno sono affatto più semplice o più conveniente, ma la versione generica nasconde ciò che sta accadendo, mentre le versioni "grezzi" ogni mettere in chiaro se ci sarà un lancio o un null.

(Questo può essere irrilevante per voi se il vostro esempio è semplificato dal codice vero e proprio).

Altri suggerimenti

Non è possibile utilizzare l'operatore as con un tipo generico senza alcuna restrizione. Dal momento che l'operatore utilizza as nulla per rappresentare che non era del tipo, non è possibile utilizzarlo su tipi di valore. Se si desidera utilizzare obj as T, T sarà sono per essere un tipo di riferimento.

T Execute<T>() where T : class
{
  return Execute() as T;
}

Questo piccolo pezzo di codice è una sostituzione sicura un'eccezione per il come -parola chiave:

return Execute() is T value ? value : default(T)

Si utilizza la funzione di pattern matching introdotta con C # 7. Usalo, se non si desidera limitare il parametro generico per un tipo di riferimento

Sembra che si stia semplicemente aggiungendo un metodo wrapper per la fusione del tipo che l'utente desidera, quindi solo l'aggiunta di spese generali per l'esecuzione. Per l'utente, la scrittura

int result = Execute<int>();

non è molto diverso da

int result = (int)Execute();

È possibile utilizzare il il modificatore di scrivere il risultato in una variabile di portata del chiamante, e restituire un flag booleano per dire se è riuscito:

bool Execute<T>(out T result) where T : class
{
    result = Execute() as T;
    return result != null;
}

C'è una possibilità che execute () potrebbe restituire un tipo di valore? Se è così, allora è necessario il metodo di Earwicker per i tipi di classe, e un altro metodo generico per i tipi di valore. Potrebbe essere simile a questo:

Nullable<T> ExecuteForValueType<T> where T : struct

La logica interna che metodo direbbe

object rawResult = Execute();

Quindi, dovreste ottenere il tipo di rawResult e vedere se può essere assegnato a T:

Nullable<T> finalReturnValue = null;

Type theType = rawResult.GetType();
Type tType = typeof(T);

if(tType.IsAssignableFrom(theType))
{
    finalReturnValue = tType;     
}

return finalReturnValue;

Infine, rendere il vostro originale Esegui figura messaggio fuori che T è ha (classe o struct tipo), e chiamare l'implementazione appropriata.

Nota: Questo è dalla memoria massima. Ho fatto questo circa un anno fa e, probabilmente, non ricordo ogni dettaglio. Ancora, spero che punta nella direzione generale, aiuta.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top