2013-01-05 15 views
5

我讀C# AsEnumerable:。爲什麼要將AsEnumerable()方法應用於數組?

「IEnumerable接口是一個通用接口,這意味着它 定義類型可以實施循環模板的 AsEnumerable方法,一個通用的方法,可以讓你蒙上了具體 類型與其等效的IEnumerable」

此外上,一個代碼示例:

using System; 
using System.Linq; 

class Program 
{ 
    static void Main() 
    { 
     // Create an array type. 
     int[] array = new int[2]; 
     array[0] = 5; 
     array[1] = 6; 
     // Call AsEnumerable method. 
     var query = array.AsEnumerable(); 
     foreach (var element in query) 
     { 
      Console.WriteLine(element); 
     } 
    } 
} 

聽起來像我需要將數組轉換爲IEnumerable類型的對象使用循環(foreach?)。

但是施加的foreach直接與陣列產率完全相同的結果:

using System; 
//using System.Linq; 

class Program 
{ 
    static void Main() 
    { 
     // Create an array type. 
     int[] array = new int[2]; 
     array[0] = 5; 
     array[1] = 6; 
     // Call AsEnumerable method. 
     //var query = array.AsEnumerable(); 
     foreach (var element in array) 
     { 
      Console.WriteLine(element); 
     } 
    } 
} 

所以,用AsEnumerable()方法進行說明的整個網頁是無效的我。
我錯過了什麼?

+3

+1這個例子完全是愚蠢的,網頁的作者也不知道'AsEnumerable'用於什麼。 –

+1

感謝所有回覆者的幫助,特別是評論員[@Konrad Rudolph](http://stackoverflow.com/users/1968/konrad-rudolph)讓我擺脫困境,與感興趣語法的人混淆的方法使用。問題的關鍵是我(而不是引用的文章,我在提問之前理解的)錯過了。我幾次閱讀所有的答案,但我更喜歡附上的代碼插圖,而不是閱讀非常明智和正確的理論。似乎正確的答案爲了麻煩教育我而遭受了倒退。 –

回答

4

這個例子不好,應該感覺不好。這裏是一個更好的,如果有點做作例如:

如果我對定義的擴展方法,讓我們說,數組類型,像這樣:

public static class ArrayExtension { 

    public static bool Any<T>(this T[] source, Func<T,bool> predicate) 
    { 
     Console.WriteLine("Undesirable side behaviour"); 
     SomeResourceIntensiveOperation(); 

     Console.WriteLine("Inefficient implementation"); 
     return source.Where(predicate).Count() != 0; 
    } 

} 

和我做

int[] nums = new []{1,2,3,4,5}; 
nums.Any(n=> n % 2 == 0); 

如果將執行並運行我的實現,即使我不需要。在做

nums.AsEnumerable().Any(n => n % 2 == 0); 

它會調用默認實現。

真正的好處是,當您使用IQueryable實施方式(例如LINQ到SQL),因爲,例如,Where for IEnumerable被定義爲

public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source, 
Func<TSource, bool> predicate) 

IQueryable.Where

public static IQueryable<TSource> Where<TSource>(
this IQueryable<TSource> source, 
Expression<Func<TSource, bool>> predicate) 
定義

當IQueryable行爲不可取時,可以調用AsEnumerable()來強制IEnumerable行爲。

+0

對不起,這是我見過的最荒謬的例子。規則例如:KISS。儘可能簡單。爲了讓你做出一點。你有那麼多不那麼好的解釋,可能甚至可能不是已經存在並且交叉引用 - 我只是希望你認真地寫下一本編程教程。 – TomTom

+5

@TomTom你必須完全擺脫你的搖桿。這個例子是AsEnumerable的完美例證。特別是,它是一個**最小的**例子。它只包含最少的成分來說明其用法。我建議你也許會在這上面睡一晚,然後再回來再看一遍。 –

+0

@TomTom我總是喜歡KISS上的一個變體:「儘量簡單,但不簡單。」 :)我真的不認爲,當我解釋擴展方法時,提出擴展方法是過度複雜的事情。 – SWeko

1

在你的例子中邏輯上沒有意義(即從數組)。我會假設第一個代碼是由初學者編寫的,或者更多下來 - 一個例子。

它在LINQ意義上是合理的,因爲「AsEnumerable」觸發對查詢的評估,並取決於ORM。這可能意味着釋放數據庫連接以便在循環內重用。

那說的:

你讀了太多例子。在一個例子中,代碼不是「好」的,而是顯示一個點。在這種情況下,演示如何使用AsEnumerable可能是有意義的 - 並且Array是最快的可枚舉對象(用代碼行來初始化),以保持示例簡短。例子指出了具體的東西,它們不是任何東西的「好代碼」。

+1

我不同意。就像你說的那樣,「在一個例子中,代碼在那裏......以顯示一個點」。這個問題中的例子完全沒有做到這一點,因爲在數組中應用'AsEnumerable'有* no *點。一個很好的例子會顯示使用它和不在LINQ to SQL查詢中使用它的區別。你讀過OP鏈接到的網站嗎?它的作者完全無能爲力。 –

+0

它從語法的角度演示了用法。 – TomTom

+1

這有什麼相關或有幫助?沒有人需要被告知如何調用一些常用的方法。他們同樣可以通過調用具有化名的'foo.Bar()'來表現出同樣的效果,甚至不需要提及'System.Array'和'AsEnumerable'。這個例子沒有顯示出更多的內容。 –

2

MSDN

AsEnumerable<TSource>的(IEnumerable<TSource>)方法以外的其他來源的編譯時間類型從實現IEnumerable<T>IEnumerable<T>本身類型改變沒有任何影響。

AsEnumerable<TSource>IEnumerable<TSource>)可以用於在序列實現IEnumerable<T>時的查詢實現之間進行選擇,但也有一組不同的公共查詢方法可用。例如,給定實現IEnumerable<T>且具有其自己的方法(如WhereSelectSelectMany)的泛型類表,則調用Where將調用表的公共Where方法。表示數據庫表的Table類型可以有一個Where方法,該方法將謂詞參數作爲表達式樹並將樹轉換爲SQL以供遠程執行。如果不需要遠程執行,例如因爲謂詞調用本地方法,則可以使用AsEnumerable<TSource>方法來隱藏自定義方法,而是使標準查詢運算符可用。

0

這只是另一個例子。假設我有這樣的方法:

static void MyMeth(int[] numbers) 
{ 
    var query = numbers.Reverse(); // works fine, calls Linq extension 

    // ... use query ... 
} 

於是我決定改變numbersList<int>代替,並嘗試:

static void MyMeth(List<int> numbers) 
{ 
    var query = numbers.Reverse(); // will not compile! 

    // ... use query ... 
} 

這裏的問題是,List<>類有另一方法,這也是稱爲Reverse。該方法返回void(因爲它在原地修改了原始的List<>)。我不想那樣。一個解決辦法是上溯造型numbers明確:

static void MyMeth(List<int> numbers) 
{ 
    var query = ((IEnumerable<int>)numbers).Reverse(); // fine; Linq 

    // ... use query ... 
} 

但另一種解決方案是AsEnumerable<>,所以:

static void MyMeth(List<int> numbers) 
{ 
    var query = numbers.AsEnumerable().Reverse(); // fine too; Linq 

    // ... use query ... 
} 

結論:AsEnumerable方法的目的是爲了「忘記」在專門的方法在一般類型IEnumerable<>上恰好「隱藏」擴展方法的類型。在「專用」類型是/繼承IQueryable<>的情況下,這可能是非常重要的,其中有(擴展)方法WhereSelect等做了一些不同的事情(即將lambda攝入爲表達式樹,分析它並「翻譯「它到SQL或東西)比WhereSelectIEnumerable<>

相關問題