[英]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.