1

我想创建一个拆分扩展,允许我将任何字符串拆分为强类型列表。我有一个先机,但由于我打算在许多项目中重用它,我想从社区获得输入(这样你就可以将它添加到你自己的工具箱中;)这里有什么想法吗?

public static class Converters
{
    public static IEnumerable<T> Split<T>(this string source, char delimiter)
    {
        var type = typeof(T);

        //SPLIT TO INTEGER LIST
        if (type == typeof(int))
        {
            return source.Split(delimiter).Select(n => int.Parse(n)) as IEnumerable<T>;
        }

        //SPLIT TO FLOAT LIST
        if (type == typeof(float))
        {
            return source.Split(delimiter).Select(n => float.Parse(n)) as IEnumerable<T>;
        }

        //SPLIT TO DOUBLE LIST
        if (type == typeof(double))
        {
            return source.Split(delimiter).Select(n => double.Parse(n)) as IEnumerable<T>;
        }

        //SPLIT TO DECIMAL LIST
        if (type == typeof(decimal))
        {
            return source.Split(delimiter).Select(n => decimal.Parse(n)) as IEnumerable<T>;
        }

        //SPLIT TO DATE LIST
        if (type == typeof(DateTime))
        {
            return source.Split(delimiter).Select(n => DateTime.Parse(n)) as IEnumerable<T>;
        }

        //USE DEFAULT SPLIT IF NO SPECIAL CASE DEFINED
        return source.Split(delimiter) as IEnumerable<T>;
    }
}
4

4 回答 4

9

我会为转换函数添加一个参数:

public static IEnumerable<T> Split<T>(this string source, Func<string, T> converter, params char[] delimiters)
{
    return source.Split(delimiters).Select(converter);
}

你可以把它称为

IEnumerable<int> ints = "1,2,3".Split<int>(int.Parse, ',');

我还会考虑重命名它以避免与String.Split实例方法混淆,因为这会使重载解析复杂化,并且行为与其他方法不同。

编辑:如果您不想指定转换功能,您可以使用类型转换器:

public static IEnumerable<T> SplitConvert<T>(this string str, params char[] delimiters)
{
    var converter = TypeDescriptor.GetConverter(typeof(T));
    if (converter.CanConvertFrom(typeof(string)))
    {
        return str.Split(delimiters).Select(s => (T)converter.ConvertFromString(s));
    }
    else throw new InvalidOperationException("Cannot convert type");
}

这允许将转换扩展到其他类型,而不是依赖于预定义的列表。

于 2012-06-02T11:15:01.240 回答
5

虽然我同意 Lee 的建议,但我个人认为不值得为标准 LINQ 操作可能很容易实现的事情定义新的扩展方法:

IEnumerable<int> ints = "1,2,3".Split(',').Select(int.Parse);
于 2012-06-02T11:41:18.623 回答
2
public static IEnumerable<T> Split<T>
      (this string source, char delimiter,Converter<string,T> func)
{
     return source.Split(delimiter).Select(n => func(n)));
}

例子:

"...".Split<int>(',',p=>int.Parse(p))

或者您可以使用 Converter.ChangeType 而不使用定义功能:

public static IEnumerable<T> Split<T>(this string source, char delimiter)
{
     return source.Split(delimiter).Select(n => (T)Convert.ChangeType(n, typeof(T)));
}
于 2012-06-02T11:23:27.843 回答
1

我不喜欢这种方法。当您处理比int. 例如,使用当前文化DateTime.Parse解析日期,因此您的方法不会为跨系统的日期提供一致或可靠的输出。它还尝试不惜一切代价解析日期,因此它可能会跳过在某些情况下可能被视为错误输入的内容。

使用硬编码转换的单一方法无法真正实现将任何字符串拆分为强类型列表的目标,特别是如果您的目标是广泛的可用性。即使您确实使用新的转换反复更新它。最好的方法就是"1,2,3".Split(",").Select(x => whatever)像上面建议的道格拉斯一样。也很清楚正在发生什么样的转换。

于 2012-06-02T12:19:04.023 回答