Split string extension with generic type?

巧了我就是萌 提交于 2019-12-13 01:34:02

问题


I would like to create a Split extension that would allow me to split any string to a strongly-typed list. I have a head start, but since I was going to reuse this in many projects, I would like to get input from the community (and so you can add it to your own toolbox ;) Any ideas from here?

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

回答1:


Although I agree with Lee’s suggestion, I personally don’t think it’s worth defining a new extension method for something that may trivially be achieved with standard LINQ operations:

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



回答2:


I'd add a parameter for the conversion function:

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

And you can call it as

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

I would also consider renaming it to avoid confusion with the String.Split instance method since this complicates overload resolution, and behaves differently to the others.

EDIT: If you don't want to specify the conversion function, you could use type converters:

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

This allows the conversion to be extended to other types rather than relying on a pre-defined list.




回答3:


public static IEnumerable<T> Split<T>
      (this string source, char delimiter,Converter<string,T> func)
{
     return source.Split(delimiter).Select(n => func(n)));
}

Example:

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

Or you can use Converter.ChangeType without define function:

public static IEnumerable<T> Split<T>(this string source, char delimiter)
{
     return source.Split(delimiter).Select(n => (T)Convert.ChangeType(n, typeof(T)));
}



回答4:


I don't like this method. Parsing data types from strings (a sort of deserialization) is a very type- and content- sensitive process when you're dealing with data types more complex than an int. For example, DateTime.Parse parses the date using the current culture, so your method is not going to provide consistent or reliable output for dates across systems. It also tries to parse the date at all costs so it might skip through what might be considered bad input in some situations.

The goal of splitting any string into a strongly typed list cannot really be accomplished with a single method that uses hard-coded conversions, especially if your goal is broad usability. Even if you do update it repeatedly with new conversions. The best way to go about it is just to "1,2,3".Split(",").Select(x => whatever) like Douglas suggested above. It's also very clear what sort of conversion is taking place.



来源:https://stackoverflow.com/questions/10861833/split-string-extension-with-generic-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!