簡體   English   中英

C#中的泛型和函數

[英]Generics and Functions in C#

這是一些代碼,它不會編譯,但是本質上我想創建的函數是解析為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那樣進行而無需調用方法。

您的parser函數簽名在parser上不正確,應定義如下。

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

請注意,在定義通用函數時,需要在函數名稱之后和參數列表之前指定通用參數(請參見上面的parser<T> )。

也許我缺少了一些東西,但是我認為這是您需要的:

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);
   }
}

從用法上來說,我需要一個返回IEnumerable<>而不是Func<>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:如果您不需要將異常處理放入解析器中(並且我希望示例代碼中僅包含空捕獲),則可以消除List<T> items而使用yield return

試試看 我認為這可以完成您要嘗試做的事情,而不會產生很多麻煩。

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));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM