2010-10-07 8 views
2

je sélectionne une double valeur de IEnumerable, comment surcharger la fonction FirstOrDefault(), pour revenir nulle en cas de défaut, au lieu de zéro, quelque chose comme iwant:C# LINQ FirstOrDefault()

double? x = from ... .FirstOrDefault(); 

i maintenant je peux attraper l'exception, et écrire en double? x = null, mais j'ai 20 variables, et ce n'est pas le cas

Répondre

9

Pourquoi ne pas faire simplement:

double? x = myDoubles.Cast<double?>().FirstOrDefault(); 
1

Si je comprends bien, vous pouvez créer une méthode d'extension en fonction de votre objectif particulier.

qui vous permettra d'utiliser la syntaxe:

double? d = (linq expression).MyCustomFirstOrNull(); 

http://msdn.microsoft.com/en-us/library/bb383977.aspx

Voir cet exemple aussi pour la syntaxe générale des méthodes d'extension:

using System.Linq; 
using System.Text; 
using System; 

namespace CustomExtensions 
{ 
    //Extension methods must be defined in a static class 
    public static class StringExtension 
    { 
     // This is the extension method. 
     // The first parameter takes the "this" modifier 
     // and specifies the type for which the method is defined. 
     public static int WordCount(this String str) 
     { 
      return str.Split(new char[] {' ', '.','?'}, StringSplitOptions.RemoveEmptyEntries).Length; 
     } 
    } 
} 
namespace Extension_Methods_Simple 
{ 
    //Import the extension method namespace. 
    using CustomExtensions; 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      string s = "The quick brown fox jumped over the lazy dog."; 
      // Call the method as if it were an 
      // instance method on the type. Note that the first 
      // parameter is not specified by the calling code. 
      int i = s.WordCount(); 
      System.Console.WriteLine("Word count of s is {0}", i); 
     } 
    } 
} 

http://msdn.microsoft.com/en-us/library/bb311042.aspx

+0

can u plz donner le lien où je peux lire sur les extensions, je ne sais pas quoi que ce soit à propos de LINQ – eba

+0

syntaxe générale est bonne), mais rien LINQ – eba

+0

@eba - vous avez demandé sur la façon de « surcharge » la méthode FirstOrDefault. Ceci est fait via des méthodes d'extension dans .Net et n'est pas limité à Linq. Eric a fourni un bon exemple pour votre situation spécifique. –

16

Don pas attraper l'exception. Le but de l'exception est de vous dire que vous avez un bug, de ne pas agir comme un flux de contrôle.

Il est assez simple d'écrire votre propre méthode d'extension qui fait ce que vous voulez, donc faire:

public static double? FirstOrNull(this IEnumerable<double> items) 
{ 
    foreach(double item in items) 
     return item; 
    return null; 
} 

Ou, si vous voulez être colombophile à ce sujet:

public static T? FirstOrNull<T>(this IEnumerable<T> items) where T : struct 
{ 
    foreach(T item in items) 
     return item; 
    return null; 
} 

Marque sens?

1

Je ne sais pas quel type de requêtes utilisez-vous. Mais si vous travaillez avec IEnumerable, vous pouvez essayer le code suivant:

double? x = (/*Some IEnumerable here*/).OfType<double?>().FirstOrDefault(); 

Mais si vous vous souciez des performances vous meilleures méthodes d'extension d'utilisation.

+0

Avez-vous réellement essayé ceci sur une séquence de doubles? Qu'est-il arrivé? –

+0

Bien sûr, je l'ai essayé avec la liste et cela a fonctionné exactement comme prévu, c'est-à-dire null pour la liste vide et la première valeur sinon. –

5

Vous pouvez écrire suivant la méthode d'extension, Je viens arnaquer Code de méthode FirstOrDefault utilisant réflecteur et amendées pour répondre à vos besoins.

public static class MyExtension 
{ 
    public static TSource? NullOrFirst<TSource>(this IEnumerable<TSource> source) where TSource : struct 
    { 
     if (source == null) 
     { 
      throw new ArgumentNullException("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 null; 
    } 
}