如何将非泛型集合转换为泛型集合?

7

最近我一直在自学LINQ,并将其应用于各种小问题。然而,我遇到的一个问题是,LINQ-to-objects只适用于泛型集合。是否有将非泛型集合转换为泛型集合的秘诀或最佳实践呢?

我的当前实现方式是将非泛型集合复制到数组中,然后对其进行操作,但我想知道是否有更好的方法?

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();
}
3个回答

11

通常最简单的方法是使用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);
}
如果你有一个集合,其中包含一些正确类型的元素,但也可能有一些不是,那么你可以使用OfType。 当Cast遇到“错误”类型的项目时会抛出异常;OfType只是跳过它们。

非常感谢!我不确定我怎么错过了文档中的那个方法,但那正是我在寻找的!此外,感谢您提供使用Max()函数的提示。 - guhou

1

您可以在 IEnumerable 上使用 CastOfType 进行转换。如果元素无法转换为指定类型,则 Cast 会抛出非法转换异常,而 OfType 将跳过任何无法进行转换的元素。


0
matches.Cast<Match>();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接