2010-02-17 103 views
7

我一直在教自己的LINQ最近,並將其應用於各種小拼圖。然而,我遇到的一個問題是,LINQ到對象只能用於泛型集合。是否有將非泛型集合轉換爲泛型集合的祕密技巧/最佳實踐?將非泛型集合轉換爲泛型集合的最佳方式是什麼?

我目前的實現將非泛型集合複製到一個數組,然後對其進行操作,但我想知道是否有更好的方法?

public static int maxSequence(string str) 
{ 
    MatchCollection matches = Regex.Matches(str, "H+|T+"); 
    Match[] matchArr = new Match[matches.Count]; 
    matches.CopyTo(matchArr, 0); 
    return matchArr 
     .Select(match => match.Value.Length) 
     .OrderByDescending(len => len) 
     .First(); 
} 

回答

10

最簡單的方法通常是Cast擴展方法:

IEnumerable<Match> strongMatches = matches.Cast<Match>(); 

注意,這是推遲和溪流的數據,所以你不要有一個完整的「集合」這樣 - 但它是LINQ查詢的完美數據源。如果您指定的查詢表達式的範圍變量類型

Cast被自動調用:

因此,要完全按照自己的查詢轉換:

public static int MaxSequence(string str) 
{  
    return (from Match match in Regex.Matches(str, "H+|T+") 
      select match.Value.Length into matchLength 
      orderby matchLength descending 
      select matchLength).First(); 
} 

public static int MaxSequence(string str) 
{  
    MatchCollection matches = Regex.Matches(str, "H+|T+"); 
    return matches.Cast<Match>() 
        .Select(match => match.Value.Length) 
        .OrderByDescending(len => len) 
        .First(); 
} 

事實上,您不需要撥打OrderByDescending,然後在這裏撥打First - 您只需要最大值,即Max方法得到你。更妙的是,它可以讓你從指定源元素類型,你要查找的數值的投影,這樣你就可以不Select做太多:

public static int MaxSequence(string str) 
{  
    MatchCollection matches = Regex.Matches(str, "H+|T+"); 
    return matches.Cast<Match>() 
        .Max(match => match.Value.Length); 
} 

如果你有其中有一些一個集合正確類型的元素,但有些可能不是,您可以改爲使用OfTypeCast當遇到「錯誤」類型的項目時拋出異常; OfType只是跳過它。

+0

非常感謝!我不確定我是如何錯過文檔中的這種方法的,但那正是我一直在尋找的!還要感謝關於使用Max()的提示 – guhou 2010-02-17 07:21:05

0
matches.Cast<Match>(); 
1

您可以使用CastOfType上的IEnumerable進行轉換。 Cast將拋出非法強制轉換,如果元素不能轉換爲指定類型,而OfType將跳過任何無法轉換的元素。