Writing an anonymous method for a method in IEnumerable

I have the following code (call to a method that returns IEnumerable):

    FibonacciWithLinq.Skip(delegate() {

                                          return 5;

    }
        );

      

The skip parameter takes an int (the number of items to skip). I could have a separate function to determine this number (this may depend on some factors). However, if the method will be consumed by the Skip () method, then it would be a good idea to write it as an anons method. The problem is, in the above code, I am getting this error:

Type arguments cannot be deprecated. Try to specify type arguments explicitly.

But I don't see anything wrong with this code. What can I do? I'm sure it is possible to write an anon method for the above scenario?

thanks

0


a source to share


5 answers


There is no automatic conversion between "value" and "no argument function that returns a value" (let him call it Func<T>

), and there is no automatic conversion in the opposite direction.

To convert a Func<T>

to a value T

, you must place ()

after it. To convert a value to Func<T>

, you can put in front of it () =>

.

If you want to call any method that accepts Func<T>

, you cannot pass it directly, so you need to convert that value to Func<T>

, and for that you can put () =>

in front of it.

If you want to call any method that takes a value, you cannot pass it directly Func<T>

, so you need to convert that Func<T>

to a value by placing ()

after it.

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

In your case, you have a function that takes a value, and you are trying to pass a function to it even if you already have a value, so you don't have to do anything other than 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 method" syntax is just the ugly old way of doing it. There are two problems with what you are trying to do (except that it is optional).

First, you need to give the compiler a type hint by explicitly specifying the type of the delegate using a wrapper new Func<int>(...)

.

Second, you need to add ()

after that to get the value.

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

      

But this cannot be stressed enough - it is completely pointless.

+3


a source


If you have something to determine how much to skip, just write:

FibonacciWithLinq.Skip(HowManyToSkip())

      

Or do you want it to be parameterized differently, for example:

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

      



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

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

      

Note that the lambda syntax is just short:

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

      

+2


a source


If you want to pass a function as an argument, then you will 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 items you want to skip.

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

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

      

+2


a source


If I am not mistaken, the correct code is simply:

FibonacciWithLinq.Skip(5);

      

EDIT :: Oh, you only want indirection for the sake of indirection. I'm guessing 5 levels of indirection is enough since we are 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);

      

+1


a source


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

      

+1


a source







All Articles