代码之家  ›  专栏  ›  技术社区  ›  cllpse

不使用反射返回IEnumerable<T>的泛型扩展方法

  •  4
  • cllpse  · 技术社区  · 16 年前

    考虑这个代码片段:

    public static class MatchCollectionExtensions
    {
        public static IEnumerable<T> AsEnumerable<T>(this MatchCollection mc)
        {
            return new T[mc.Count];
        }
    }
    

    public class Ingredient
    {
        public String Name { get; set; }
    }
    

    有没有什么方法可以神奇地改变 MatchCollection Ingredient ? 用例如下所示:

    var matches = new Regex("([a-z])+,?").Matches("tomato,potato,carrot");
    
    var ingredients = matches.AsEnumerable<Ingredient>();
    


    更新

    一个纯粹的基于LINQ的解决方案也就足够了。

    3 回复  |  直到 16 年前
        1
  •  4
  •   itowlson    16 年前

    只有当你有办法把一个匹配的成分。由于没有一种通用的方法来实现这一点,您可能需要给您的方法一些帮助。例如,您的方法可能需要 Func<Match, Ingredient> 要执行映射:

    public static IEnumerable<T> AsEnumerable<T>(this MatchCollection mc, Func<Match, T> maker)
    {
      foreach (Match m in mc)
        yield return maker(m);
    }
    

    你可以这样称呼它:

    var ingredients = matches.AsEnumerable<Ingredient>(m => new Ingredient { Name = m.Value });
    

    您也可以绕过创建自己的方法,只使用Select,并使用Cast操作符来处理MatchCollection的弱类型:

    var ingredients = matches.Cast<Match>()
                             .Select(m => new Ingredient { Name = m.Value });
    
        2
  •  2
  •   Andrew Bezzub    16 年前

    System.Linq 命名空间):

    public class Ingredient
    {
        public string Name { get; set; }
    }
    
    public static class MatchCollectionExtensions
    {
        public static IEnumerable<T> AsEnumerable<T>(this MatchCollection mc, Func<Match, T> converter)
        {
            return (mc).Cast<Match>().Select(converter).ToList();
        }
    }
    

    可以这样使用:

        var matches = new Regex("([a-z])+,?").Matches("tomato,potato,carrot");
    
        var ingredients = matches.AsEnumerable<Ingredient>(match => new Ingredient { Name = match.Value });
    
        3
  •  2
  •   Marcelo Cantos    16 年前

    你可以先投。。。

    matches.Cast<Match>()
    

    IEnumerable<Match> 但是你想使用LINQ。