2010-09-30 11 views
1

Juste pour des raisons de test, je définis mon cas-Méthode de LINQ comme ceci:Définition de ma propre méthode Where pour LINQ to Objects - Comment savoir lequel sera utilisé?

namespace Test 
{ 
    public static class LinqTest 
    { 
     public static IEnumerable<TSource> Where<TSource>(
         this IEnumerable<TSource> source, 
         Func<TSource, bool> predicate) 
     { 
      return new List<TSource> { }; 
     } 
    } 
} 

Donc, si j'utilise une requête comme ça, je n'obtenir un résultat:

var test = new string[]{ "a", "b", "c" }; 
    var x = from y in test 
      where y.Length > 0 
      select y; 
    foreach (var element in x) 
     Console.WriteLine(element); 

Ma question est: Comment le compilateur sait-il quelle méthode d'extension est supposée être appelée? Celui inclus dans LINQ, ou celui défini par l'utilisateur?

Cheers, Chris

+0

Et comment le mainteneur de votre code sait-il qui est utilisé? Cela semble être une mauvaise chose à faire. – Henrik

+0

Je suis totalement d'accord. Je l'ai fait juste par intérêt. Je ne prévois pas de le faire dans une application réelle. – Christopher

Répondre

3

Les règles de méthode d'extension sont similaires à ceux pour la recherche d'appel de méthode normale. La version courte est le compilateur qui trouvera toutes les méthodes et méthodes d'extension qui sont accessibles et choisiront la meilleure correspondance parmi celles-ci (les méthodes sans extension étant préférées aux méthodes d'extension).

Tout comme les méthodes normales, le choix de la méthode d'extension à utiliser peut être ambigu. Ce serait le cas ici si les espaces de noms System.Linq et Test étaient utilisés dans l'application. En fonction de vos informations, il semble que l'espace de noms de test ne soit pas référencé avec un using, donc il ne sera pas considéré et la version Linq l'emporte.

Remarque: Ce qui précède est un résumé de la façon dont la recherche se produit et n'est en aucun cas définitive. La spécification de langage C# est l'autorité ici et la couvre de façon beaucoup plus détaillée.

+0

Merci, je viens de le tester dans mon petit exemple: Si tout est dans le même espace de noms, la version définie par l'utilisateur gagne. Sinon, la version LINQ gagne. – Christopher

+0

@Christopher aussi si vous le mettez dans un espace de noms séparé et 'using 'à la fois' System.Linq' et 'Test' alors il va faire une erreur. – JaredPar

1

Normalement, si vous déclarez des extensions en conflit, vous obtiendrez une erreur de compilation lorsque vous essaierez de l'utiliser. Cependant, apparemment, si l'extension est définie dans le même espace de noms, elle est prioritaire sans donner d'erreur ni même d'avertissement.

+0

On dirait que vous avez parfaitement raison, si je mets la classe LinqTest dans un autre espace de noms et que je la référence avec une instruction using, j'obtiens l'erreur "L'appel est ambigu entre les méthodes suivantes ..." – Christopher