2011-07-19 14 views
6

Sono stanco di scrivere:Fine di funzioni superiore nella gerarchia delle

if(objectA!=null) 
return; 

o:

if(objectB==null) 
return; 

quindi ero la speranza di accorciare questo frammento di codice, a qualcosa di simile:

Returns.IfNull(objectA); 

è abbastanza simile alla stessa lunghezza ma di solito ci sono pochi oggetti da controllare e aggiungere params come parametro può abbreviare:

if(objectA==null || objectB!=null || objectC!=null) 
return; 

a:

Returns.IfNull(objectA,objectB,objectC); 

funzionano Fondamentalmente IfNull avere per ottenere l'accesso alla funzione di un gradino più alto nella traccia dello stack e finirlo. Ma è solo un'idea, non so se è possibile. Posso trovare una logica simile in qualche lib?

+0

Ciò che si desidera è essenzialmente un metodo di estensione, anche se leggermente diverso con la classe 'Returns' ... – IAbstract

+1

Come sarebbe il vostro metodo IfNull sapere se verificare è nullo o non è nullo come il vostro esempio precedente? –

+1

@IAbstract: anche allora un metodo di estensione non può "restituire" la funzione sopra di esso nello stack –

risposta

7

No, si sta essenzialmente chiedendo alla funzione di uscire dalla funzione più alta di sé che non è auspicabile né realmente possibile a meno che non si lanci un'eccezione (che non restituisce di per sé).

Quindi, puoi eseguire i tuoi assegni se-null-return semplici e concisi, o quello che potresti voler fare è invece lanciare un'eccezione ben definita, ma non consiglio eccezioni per il controllo del flusso. Se si tratta di circostanze eccezionali (errore), tuttavia, prendere in considerazione la possibilità di lanciare ArgumentNullException() e gestirlo in modo appropriato.

Si potrebbe scrivere alcuni metodi di supporto per gettare ArgumentNullException() per voi, naturalmente, di ripulirlo un po ':

public static class ArgumentHelper 
    { 
     public static void VerifyNotNull(object theObject) 
     { 
      if (theObject == null) 
      { 
       throw new ArgumentNullException(); 
      } 
     } 

     public static void VerifyNotNull(params object[] theObjects) 
     { 
      if (theObjects.Any(o => o == null)) 
      { 
       throw new ArgumentNullException(); 
      } 
     } 
    } 

allora si potrebbe scrivere:

public void SomeMethod(object obj1, object obj2, object obj3) 
{ 
    ArgumentHelper.VerifyNotNull(obj1, obj2, obj3); 

    // if we get here we are good! 
} 

Ma ancora una volta , questa è un'eccezione e non un "ritorno" del metodo precedente nello stack, che non è direttamente possibile.

+1

Tuttavia, il chiamante può ancora rilevare l'eccezione e rifiuta ostinatamente di tornare presto. –

+1

Molto vero :-) ma è l'unico modo per dire al metodo sopra potenzialmente di uscire (se non gestito) ... –

+1

Forse un goto potrebbe funzionare: p: D –

0

Non è possibile richiamare un altro metodo e aspettarsi di tornare al punto di chiamata del metodo corrente (è possibile se si abbia qualcosa come lo stile di passaggio di continuazione, purtroppo non lo facciamo).

Si potrebbe dire:

if(new[] { objectA, objectB, objectC }.Any(x => x != null)) { 
    return; 
} 

Oppure:

if(new[] { objectA, objectB, objectC }.AnyAreNotNull()) { 
    return; 
} 

Qui, AnyAreNotNull è:

public static class EnumerableExtensions { 
    public static bool AnyAreNotNull<T>(this IEnumerable<T> source) { 
     Contract.Requires(source != null); 
     return source.Any(x => x != null); 
    } 
} 

Ma in realtà, non c'è niente di sbagliato con solo la scrittura del codice usuale per questa situazione.

+4

Questo è altrettanto brutto, e direi, molto più confuso del semplice controllo che stava facendo sopra.:) –

+0

Sì, in questo caso direi che meno è di più ... Creare una colletta per vedere se qualcuno fosse nullo sembra un po 'eccessivo. Personalmente mi piace controllarli e poi lanciare ArgumentNullException, ma questo sta fornendo che sta bene con le eccezioni ... –

+0

@George: Su quel punto siamo d'accordo. – jason

0

No, un metodo non può restituire il metodo sopra di esso.

La cosa migliore da fare è creare un metodo che restituisce true se uno dei suoi parametri era nullo, quindi fare if (ReturnHelper.AllNull(obj1, obj2, obj3)) return; ma direi che è molto meno leggibile.

1

Stai chiedendo qualcosa che solo il designer del linguaggio può risolvere per te. Ho proposto una cosa per myself. Il.? l'operatore ritorna dal metodo corrente con il valore di ritorno predefinito quando l'argomento lasciato ad esso è nullo.

return appSettings.?GetElementKey(key).?Value ?? ""; 

Forse lo vedremo un giorno in C# 6?

+0

Mi auguro una cosa del genere – Twelve

1

Per fare controlli di confronto simili una volta ho definito il seguente metodo di estensione:

/// <summary> 
/// Returns whether the object equals any of the given values. 
/// </summary> 
/// <param name = "source">The source for this extension method.</param> 
/// <param name = "toCompare">The objects to compare with.</param> 
/// <returns> 
/// True when the object equals any of the passed objects, false otherwise. 
/// </returns> 
public static bool EqualsAny(this object source, params object[] toCompare) 
{ 
    return toCompare.Any(o => o.Equals(source)); 
} 

Si può semplificare i controlli ridondanti, ad esempio:

string someString = "bleh"; 
bool anyEquals = someString.EqualsAny("bleh", "bloeh"); 

Nel tuo caso in cui si controlla per più controlli nulli voi potrebbe utilizzarlo come segue:

if (EqualsAny(null, objectA, objectB, objectX)) return; 

In un'altra nota, il codice mi ricorda di Code Contracts che consente di definire le condizioni pre e post. Nel caso in cui questo è il tuo scenario - forse non perché non vedo perché si chiama return - potrebbe interessarti. Una parte di esso è disponibile gratuitamente in .NET 4.0.

Problemi correlati