代码之家  ›  专栏  ›  技术社区  ›  Michael Edwards

C语言中的泛型与函数#

  •  2
  • Michael Edwards  · 技术社区  · 15 年前

    这是一些代码,它不会编译,但本质上我想要创建的是一个函数,它解析为CSV文件,然后将CSV列表中的值转换为特定类型。

        Func<string, Func<string,T>, IEnumerable<T>> parser =(string csv, Func<string, T> newFunc) =>
        {
            List<T> items = new List<T>();
            string[] ary = csv.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string val in ary)
            {
                try
                {
                    items.Add(newFunc(val));
                }
                catch { }
            }
            return items;
        }
    

    我希望这个函数是通用的,所以T是我希望CSV列表转换成的类型。此函数的用法如下:

     string csvList ="1,2,3";
            IEnumerable<int> list = parser(csvList, (string val) => { return Convert.ToInt32(val)});
    

    不过,这显然行不通,因为我还没有定义t。那么,是否可以用类似于泛型方法的方式定义t:

        Func<T><string, Func<string,T>, IEnumerable<T>> parser =(string csv, Func<string, T> newFunc) =>
        {
            List<T> items = new List<T>();
            string[] ary = csv.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string val in ary)
            {
                try
                {
                    items.Add(newFunc(val));
                }
                catch { }
            }
            return items;
        }
    

    然后这样使用:

    string csvList ="1,2,3";
            IEnumerable<int> list = parser<int>(csvList, (string val) => { return Convert.ToInt32(val)});
    

    在C中有没有一种方法可以做这样的事情?

    --进一步编辑

    感谢你们的回复,在我写的代码中,我实际上使用了一个像你们描述的方法,但是我只是想知道一个一般性的问题,是否可以不需要调用方法就把它作为Func来完成。

    4 回复  |  直到 15 年前
        1
  •  2
  •   BFree    15 年前

    也许我遗漏了一些东西,但我想这就是你需要的:

    public IEnumerable<T> Parse<T>(string csv, Func<string, T> func)
    {
       foreach(var item in csv.Split(new char[] {','}, StringSplitOptions.RemoveEmptyEntries))
       {
          yield return func(item);
       }
    }
    
        2
  •  2
  •   Steve Guidi    15 年前

    您的函数签名 parser

    Func<string, Func<string,T>, IEnumerable<T>>
        parser<T>(string csv, Func<string, T> newFunc)
    {
        // implementation
    }
    

    parser<T> 以上)。

        3
  •  1
  •   Henk Holterman    15 年前

    我会说你需要一个函数 IEnumerable<> ,不是 Func<>

    这会把整个过程简化为:

        IEnumerable<T> parser<T>(string csv, Func<string, T> newFunc)
        {
            List<T> items = new List<T>();
    
            string[] ary = csv.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string val in ary)
            {
                try
                {
                    items.Add(newFunc(val));
                }
                catch
                {
                    // empty catch alert
                }
            }
            return items;
        }
    

    你的用例缺少一个分号(后面 ToInt32() ) :

        string csvList ="1,2,3";
        IEnumerable<int> list = 
          parser<int>(csvList, (val) => { return Convert.ToInt32(val); });
    

    编辑,感谢BFree:如果您不需要异常处理在解析器内部(我希望空的catch只存在于示例代码中),您可以消除 List<T> items 和使用 yield return

        4
  •  0
  •   Scott P    15 年前

    试试这个。我想这就完成了你所要做的,而不需要太多的胡言乱语。

    string csvList = "1,2,3";
    IEnumerable<int> list = parser<int>(csvList, Convert.ToInt32);
    
    
    
    static IEnumerable<T> parser<T>(string csv, Converter<string, T> converter)
    {
        string[] array = csv.Split(new string[] { "," }, 
                            StringSplitOptions.RemoveEmptyEntries);
    
        T[] items = Array.ConvertAll(array, converter);
    
        return items;
    }
    

    如果你想要一条线,你可以这样做:

    string csvList = "1,2,3";
    var list = csvList.Split(new string[] { "," }, 
               StringSplitOptions.RemoveEmptyEntries).Select(x => Convert.ToInt32(x));