2009-05-25 5 views
0

J'ai le code suivant (appeler une méthode de retour IEnumerable):Rédaction d'une méthode anonyme pour une méthode IEnumerable

FibonacciWithLinq.Skip(delegate() { 

              return 5; 

    } 
     ); 

Le paramètre de saut prend un int (nombre d'éléments à sauter). Je pourrais avoir une fonction séparée qui déterminerait ce nombre (cela peut dépendre de certains facteurs). Cependant, si la méthode va être consommée par la méthode Skip(), il serait bon de l'écrire comme une méthode anon. Le problème est, dans le code ci-dessus, j'obtiens cette erreur:

Les arguments de type ne peuvent pas être déduits de l'utilisation. Essayez de spécifier explicitement les arguments de type.

Mais je ne vois rien de mal avec le code ci-dessus. Que puis-je faire? Je suis assez sûr qu'une méthode anon peut être écrite pour le scénario ci-dessus?

Merci

+0

Comment Skip est-il défini? –

+0

Il est défini ici: http://msdn.microsoft.com/en-us/library/bb358985.aspx Et il ne prend pas un délégué comme un argument, juste un nombre, donc toute cette question semble être discutable. –

Répondre

3

Il n'y a pas de conversion automatique entre une « valeur » et « une fonction sans argument qui renvoie une valeur » (appelons-un Func<T>), ni est là une conversion automatique dans le sens inverse .

Pour convertir un Func<T> en une valeur, T, vous devez mettre () après. Pour convertir une valeur en Func<T>, vous pouvez mettre () => devant.

Si vous voulez appeler une méthode qui accepte un Func<T>, vous ne pouvez pas passer directement une valeur, vous devez convertir cette valeur en un Func<T>, et pour ce faire, vous pouvez mettre () => en face de celui-ci.

Si vous souhaitez appeler une méthode qui accepte une valeur, vous ne pouvez pas lui passer directement un Func<T>, vous devez donc convertir cette Func<T> en valeur en lui attribuant la valeur ().

Certaines langues effectuent automatiquement la conversion entre ces éléments, contrairement à C#. Dans votre cas, vous avez une fonction qui accepte une valeur, et vous essayez de lui transmettre une fonction, même si vous avez déjà une valeur, donc vous n'avez rien d'autre à faire que valeur à la fonction. La syntaxe "méthodes anonymes" est juste la vieille façon laide de faire cela. Il y a deux problèmes avec ce que vous essayez de faire (mis à part le fait que ce n'est pas nécessaire).

Tout d'abord, vous devez donner un indice de type au compilateur en indiquant explicitement le type de délégué avec un wrapper new Func<int>(...). En second lieu, vous devez ajouter le () après pour obtenir la valeur.

FibonacciWithLinq.Skip(new Func<int> 
         (delegate() 
         { 
          return 5; 
         })()); 

Mais cela ne peut pas être assez souligné - c'est complètement inutile.

1

si je ne me trompe pas, le bon code est juste:

FibonacciWithLinq.Skip(5); 

EDIT :: Oh, vous voulez indirection juste pour le plaisir de indirection. Je suppose que 5 niveaux d'indirection suffisent, puisque nous sautons 5 éléments? Laissez-moi savoir si vous avez besoin de plus ...

IEnumerable<int> FibannociSkip = new int[]{0, 1, 1, 2, 3, 5}; 
Func<Func<Func<Func<Func<int>>>>> f =()=>(()=>(()=>(()=>(()=>5)))); 
foreach(var num in FibannociSkip.Skip(f()()()()())) 
    Console.WriteLine(num); 
+0

C'est parfaitement légal, mais si les méthodes anonymes ne peuvent pas être utilisées, pourquoi pas? – dotnetdev

+0

Est-ce C# ou Lisp? ; p – johnc

+0

Je vais prendre cela comme un compliment. ;) –

2

Si vous avez quelque chose qui déterminerait le nombre de sauter, il suffit d'écrire:

FibonacciWithLinq.Skip(HowManyToSkip()) 

Ou voulez-vous qu'il paramétrés d'une manière différente, comme celui-ci:

Func<int, IEnumerable<int>> skipper = x => FibonacciWithLine.Skip(x); 
foreach (var i in skipper(5)) Console.WriteLine(i); 

Le code dans votre question passe dans une méthode au lieu d'une valeur int constante, ce qui est ce que veut saut. Peut-être que vous voulez ignorer les valeurs renvoyées par la séquence: le cas échéant, la méthode d'extension Sauf() est ce que vous voulez:

FibonacciWithLinq.Except(x => (x == 5 || x == 7)); 

Notez la syntaxe lambda est un peu moins pour:

FibonacciWithLinq.Except(delegate(int x) { return x==5||x==7; }); 
2

Si vous Si vous voulez que skip prenne une fonction en tant qu'argument, alors vous devrez écrire une extension qui le fait, alors vous pouvez utiliser un délégué ou lambda pour fournir une fonction qui peut être évaluée pour ignorer les éléments que vous voulez omettre.

public static class IEnumerableExtensions 
{ 
    public static IEnumerable<T> Skip(this IEnumerable<T> source, Func<int> toSkip) 
    { 
     return source.Skip(toSkip()); 
    } 
} 

FibonacciWithLinq.Skip(() => { return 5; }); 
+0

+1 pour la réponse directe. Merci! – dotnetdev

1
Func<int> f =() => 5; 
FibonacciWithLinq.Skip(f()); 
Questions connexes