tags:

views:

192

answers:

5

I have the following code (calling a method returning IEnumerable):

    FibonacciWithLinq.Skip(delegate() {

                                          return 5;

    }
        );

The parameter for skip takes an int (number of items to skip). I could have a seperate function which would determine this number (it may be dependent on some factors). However, if the method is going to be consumed by the Skip() method, then it would be good to write it as an anon method. Problem is, in the above code, I get this error:

The type arguments cannot be inferred from the usage. Try specifying the type arguments explicitly.

But I can't see anything wrong with the above code. What can I do? I'm pretty sure an anon method can be written for the above scenario?

Thanks

+1  A: 

Unless I'm very mistaken, the correct code is just:

FibonacciWithLinq.Skip(5);

EDIT:: Oh, you want indirection just for the sake of indirection. I assume 5 levels of indirection is enough, since we're skipping 5 elements? Let me know if you need more...

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);
Matthew Flaschen
That is perfectly legal, but if anonymous methods can't be used, why not?
dotnetdev
Is that C# or Lisp? ;p
johnc
I'll take that as a compliment. ;)
Matthew Flaschen
+2  A: 

If you have something that would determine how many to skip, simply write:

FibonacciWithLinq.Skip(HowManyToSkip())

Or do you want it parameterized in a different way, such as this:

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

The code in your question is passing in a method instead of a constant int value, which is what Skip wants. Perhaps you want to skip values returned by the sequence: if so, the Except() extension method is what you want:

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

Note the lambda syntax is just short for:

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

If you want skip to take an function as an argument, then you'll need to write an extension that does this, then you can use a delegate or lambda to provide a function that can be evaluated to skip the elements that you want omitted.

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

FibonacciWithLinq.Skip( () => { return 5; } );
tvanfosson
+1 for the straightforward answer. Thanks!
dotnetdev
+1  A: 
Func<int> f = () => 5;
FibonacciWithLinq.Skip(f());
VVS
+3  A: 

There is no automatic conversion between a "value" and "a function with no arguments that returns a value" (let's call it a Func<T>), nor is there an automatic conversion in the opposite direction.

To convert a Func<T> into a value, T, you have to put () after it. To convert a value into a Func<T>, you can put () => in front of it.

If you want to call some method that accepts a Func<T>, you cannot directly pass it a value, so you have to convert that value into a Func<T>, and to do that you can put () => in front of it.

If you want to call some method that accepts a value, you cannot directly pass it a Func<T>, so you have to convert that Func<T> into a value by putting () after it.

Some languages automatically convert between these things, but C# doesn't.

In your case, you have a function that accepts a value, and you're trying to pass it a function, even though you already have a value, so you don't need to do anything special apart from give the value to the function.

int val = 5;               // value
Func<int> f = () => val;   // convert value to function
int val2 = f();            // convert back to value

The "anonymous methods" syntax is just the ugly old way of doing this. There are two problems with what you're trying to do (aside from the fact that it's unnecessary).

Firstly, you need to give the compiler a type hint by explicitly stating the delegate type with a new Func<int>(...) wrapper.

Secondly, you need to add the () after it to get the value.

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

But it can't be stressed enough - this is completely pointless.

Daniel Earwicker