2009-05-25 37 views
0

匿名方法我有以下代碼(調用返回IEnumerable的一種方法):寫作的方法中的IEnumerable

FibonacciWithLinq.Skip(delegate() { 

              return 5; 

    } 
     ); 

用於跳過參數採用int(項目數跳過)。我可以有一個單獨的函數來確定這個數字(它可能取決於一些因素)。但是,如果該方法將由Skip()方法使用,那麼將它作爲匿名方法編寫將是一件好事。問題是,在上面的代碼中,我得到這個錯誤:

無法從使用情況推斷類型參數。嘗試明確指定類型參數。

但我看不出上面的代碼有什麼問題。我能做什麼?我很確定可以爲上述場景編寫匿名方法?

感謝

+0

Skip是如何定義的? – 2009-05-25 21:27:42

+0

它的定義在這裏:http://msdn.microsoft.com/en-us/library/bb358985.aspx它並不需要委託作爲參數,只是一個數字,所以整個問題似乎都沒有實際意義。 – 2009-05-25 21:30:24

回答

3

有一個「值」和「不帶參數的一個返回值的函數」之間沒有自動轉換(讓我們稱之爲一個Func<T>),也沒有在相反方向的自動轉換。

要將Func<T>轉換爲值T,必須在其後面放置()。要將值轉換爲Func<T>,您可以在其前面放置() =>

如果你想打電話給一些接受Func<T>方法,你不能直接傳遞一個值,所以你必須將該值轉換成Func<T>,要做到這一點,你可以把() =>在它的前面。

如果你想打電話給一些接受值的方法,你不能直接傳遞一個Func<T>,所以你必須通過把()後到Func<T>轉換成數值。

有些語言在這些東西之間自動轉換,但C#沒有。

在你的情況下,你有一個函數接受一個值,並且你正在試圖傳遞一個函數,即使你已經有了一個值,所以除了賦予值的功能。

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

「匿名方法」語法就是這樣做的醜陋的舊方法。你試圖做什麼有兩個問題(除了不必要的事實)。

首先,您需要通過使用new Func<int>(...)包裝明確指定委託類型來爲編譯器提供類型提示。

其次,您需要在其後面添加()以獲取該值。

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

但它不能夠強調 - 這是完全沒有意義的。

1

除非我大錯特錯,正確的代碼就是:

FibonacciWithLinq.Skip(5); 

編輯:: ,你想間接只是間接的緣故。我認爲5級間接就足夠了,因爲我們跳過了5個元素?讓我知道如果你需要更多...

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

這是完全合法的,但如果匿名方法不能使用,爲什麼不呢? – dotnetdev 2009-05-25 20:52:00

2

如果你有一些會確定有多少個跳過,簡單地寫:

FibonacciWithLinq.Skip(HowManyToSkip()) 

還是想要它以不同的方式參數化,例如:

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

您的問題中的代碼是傳遞一個方法,而不是一個常量int值,這是Skip想要的。也許你想跳過由序列返回的值:如果是這樣,除了()擴展方法是你想要什麼:

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

注意lambda語法只是簡稱:

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

如果您想要跳過將函數作爲參數,那麼您需要編寫一個擴展來完成此操作,然後您可以使用委託或lambda來提供一個可以評估的函數,以跳過您希望省略的元素。

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

FibonacciWithLinq.Skip(() => { return 5; }); 
1
Func<int> f =() => 5; 
FibonacciWithLinq.Skip(f());