2013-04-03 9 views
15

Come posso integrare il metodo di .DefaultIfEmpty() estensione in modo non ho non utilizzareUtilizzare .DefaultIfEmpty() anziché .FirstOrDefault() ?? String.Empty;

.FirstOrDefault() ?? String.Empty; 

Codice:

(from role in roleList 
let roleArray = role.RoleId.Split(new char[] { WorkflowConstants.WorkflowRoleDelimiter }) 
where roleArray.Length.Equals(_SplittedRoleIdArrayLength) && 
     HasAccessToCurrentUnit(roleArray[_UnitIndexInRoleId]) 
select roleArray[_LevelIndexInRoleId]).FirstOrDefault() ?? String.Empty; 
+2

Personalmente non lo farei. 'DefaultIfEmpty' è interessato alle enumerables, non ai valori scalari. Crea il tuo metodo di estensione, possibilmente chiamato anche 'FirstOrDefault' che accetta un argomento' T' da specificare come predefinito. –

risposta

12

si potrebbe usare:

var query = ...; 

return query.DefaultIfEmpty(string.Empty).First(); 

Ma questo non lo fa ridurre la complessità IMO.

+0

Sì, ridurre la complessità è uno dei miei obiettivi. Qualche altro suggerimento finora hai? – Elisabeth

+1

Ciao, signor 2k. Ora sei in realtà 14k! –

+0

Sono passato alla soluzione. – Elisabeth

7

Se siete interessati a metodo di estensione, allora si potrebbe usare qualcosa di simile:

public static class Helpers 
{ 
    public static string FirstOrEmpty(this IEnumerable<string> source) 
    { 
     return source.FirstOrDefault() ?? string.Empty; 
    } 
} 

Modifica

Questo metodo non è generico perché poi avremmo dovuto usare default(T) e ci darà null anziché string.Empty.

+1

forse quindi 'T FirstOrEmpty (questa sorgente IEnumerable )' –

+1

@Ilya Ivanov, se sarà generico, il suo valore predefinito sarà ancora null per stringa. –

+1

Ma 'T FirstOrDefault (questa IEnumerable origine, T default)' sarebbe possibile. Quindi ancora, '.FirstOrDefault (string.Empty)' vs. '.FirstOrDefault() ?? string.Empty' non fa davvero molta differenza. – hvd

1

Il codice:

var query=(
    from role in roleList 
    let delimiter=WorkflowConstants.WorkflowRoleDelimiter 
    let roleArray=role.RoleId.Split(new char[] { delimiter }) 
    where roleArray.Length.Equals(_SplittedRoleIdArrayLength) 
    where HasAccessToCurrentUnit(roleArray[_UnitIndexInRoleId]) 
    select roleArray[_LevelIndexInRoleId] 
    ).DefaultIfEmpty("").FirstOrDefault(); 

Per il sospetto circa il significato semantico di DefaultIfEmpty e FirstOrDefault, segue è il codice decompilato dalla libreria:

  • Codice

    public static IEnumerable<TSource> DefaultIfEmpty<TSource>(this IEnumerable<TSource> source) 
    { 
        return source.DefaultIfEmpty<TSource>(default(TSource)); 
    } 
    
    public static IEnumerable<TSource> DefaultIfEmpty<TSource>(this IEnumerable<TSource> source, TSource defaultValue) 
    { 
        if (source == null) 
        { 
         throw Error.ArgumentNull("source"); 
        } 
        return DefaultIfEmptyIterator<TSource>(source, defaultValue); 
    } 
    
    public static TSource First<TSource>(this IEnumerable<TSource> source) 
    { 
        if (source == null) 
        { 
         throw Error.ArgumentNull("source"); 
        } 
        IList<TSource> list = source as IList<TSource>; 
        if (list != null) 
        { 
         if (list.Count > 0) 
         { 
          return list[0]; 
         } 
        } 
        else 
        { 
         using (IEnumerator<TSource> enumerator = source.GetEnumerator()) 
         { 
          if (enumerator.MoveNext()) 
          { 
           return enumerator.Current; 
          } 
         } 
        } 
        throw Error.NoElements(); 
    } 
    
    public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source) 
    { 
        if (source == null) 
        { 
         throw Error.ArgumentNull("source"); 
        } 
        IList<TSource> list = source as IList<TSource>; 
        if (list != null) 
        { 
         if (list.Count > 0) 
         { 
          return list[0]; 
         } 
        } 
        else 
        { 
         using (IEnumerator<TSource> enumerator = source.GetEnumerator()) 
         { 
          if (enumerator.MoveNext()) 
          { 
           return enumerator.Current; 
          } 
         } 
        } 
        return default(TSource); 
    } 
    

E qui sono qualcosa di parlare:

  1. DefaultIfEmpty ha un sovraccarico senza parametri, che invoca il sovraccarico parametrizzata con default(TSource) e restituisce il suo risultato.

  2. L'unica differenza tra FirstOrDefault senza parametri e First, è il secondo che genera quando la raccolta è vuota.

    Per ulteriori informazioni, vedere Enumerable.FirstOrDefault<TSource> Method su MSDN.

  3. FirstOrDefault semanticamente espresso first or default e così chiamato; non è denominato first or null. In C#, default(T) per un tipo di riferimento è null, ma per il tipo non di riferimento, non lo è. Ad esempio, default(int) è zero.

    La parola chiave default non è mai stata dichiarata null semantica. È DEFAULT.

    Inoltre, per ulteriori informazioni, default Keyword su MSDN.

+1

Your FirstOrDefault(); alla fine non ha senso Se si aspettava un valore nullo da OrDefault, la sequenza è vuota. Quindi il "" verrà restituito ... Suggerisco invece .First(). – Elisabeth

+0

@Elisa: Sì, sono uguali qui, poiché copio solo dal tuo codice e non è cambiato, ma penso che non abbia importanza. –

+0

Beh, importa. L'uso di FirstOrDefault è corretto solo al 50%. L'OrDefault (valore null) non accadrà mai e darà al lettore una falsa impressione di cosa stia facendo il codice. – Elisabeth

Problemi correlati