如何编写将分隔字符串转换为列表的通用扩展方法?

本文关键字:扩展 方法 列表 何编写 分隔 字符串 转换 | 更新日期: 2023-09-27 18:04:35

我们经常需要将值由某个字符分隔的字符串转换为列表。我想编写一个泛型扩展方法,将字符串转换为指定类型的列表。以下是目前为止的内容:

    public static List<T> ToDelimitedList<T>(this string value, string delimiter)
    {
        if (value == null)
        {
            return new List<T>();
        }
        var output = value.Split(new string[] { delimiter }, StringSplitOptions.RemoveEmptyEntries);
        return output.Select(x => (T)x).ToList();
    }

但是我得到一个错误。

不能将'string'类型转换为'T'类型。

是否有更好的方法来做到这一点,或者我是否需要为不同类型的列表创建多个扩展方法并执行Convert.ToInt32()等?

更新

我想做这样的事情:

var someStr = "123,4,56,78,100";
List<int> intList = someStr.ToDelimitedList<int>(",");

var someStr = "true;false;true;true;false";
List<bool> boolList = someStr.ToDelimitedList<bool>(";");

如何编写将分隔字符串转换为列表的通用扩展方法?

Convert.ChangeType将适用于基本类型和许多框架类型(假设默认解析规则足够好):

return output.Select(x => (T) Convert.ChangeType(x, typeof(T)))
             .ToList();

如果你需要这个为你自己的自定义类型工作,你必须让他们实现IConvertible接口。

请记住,这还不够复杂,无法与自定义转换规则一起工作,也不够健壮,无法正确处理失败(除了抛出异常并使整个操作失败之外)。如果需要对此提供支持,可以提供一个接受TypeConverter或转换委托的重载(如mike z的回答)。

没有内置的方法将字符串转换为任意类型T。你的方法必须接受某种委托:

public static List<T> ToDelimitedList<T>(this string value, string delimiter, Func<string, T> converter)
{
    if (value == null)
    {
        return new List<T>();
    }
    var output = value.Split(new string[] { delimiter }, StringSplitOptions.RemoveEmptyEntries);
    return output.Select(converter).ToList();
}

似乎你可以只使用String.SplitEnumerable.Select ?

var list = "1,2,3".Split(",").Select(s => int.Parse(s));

但是如果你必须做一个扩展,试试这个…

public static List<T> ParseDelimitedList<T>(this string value, string delimiter, Func<string, T> selector)
{
    if (value == null)
    {
        return new List<T>();
    }
    var output = value.Split(new string[] { delimiter }, StringSplitOptions.RemoveEmptyEntries);
    return output.Select(selector).ToList();
}
var list = "1,2,3".ParseDelimitedList(",", s => int.Parse(s));

这不是LINQ的完美任务吗?

你可以这样做:

"1,2,3,4,5".Split(',').Select(s => Convert.ToInt32(s)).ToList();

您可以根据您的情况更改通用 Select()委托。