ChevCast
ChevCast

Reputation: 59231

How can I write a generic extension method for converting a delimited string to a list?

We often have a need to turn a string with values separated by some character into a list. I want to write a generic extension method that will turn the string into a list of a specified type. Here is what I have so far:

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

But I get an error.

Cannot convert type 'string' to type 'T'.

Is there a better way to do this or do I need to create multiple extension methods for the different types of lists and do Convert.ToInt32(), etc?

UPDATE

I'm trying to do things like this:

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

or

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

Upvotes: 9

Views: 1086

Answers (4)

Oliver
Oliver

Reputation: 9002

Is this not a perfect task for LINQ?

You could just do something like the following:

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

You can alter the generic Select() delegate depending on your situation.

Upvotes: 6

Ani
Ani

Reputation: 113442

Convert.ChangeType will work for primitive and many framework types (assuming default parsing rules are good enough):

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

If you need this to work for your own custom types, you'll have to get them to implement the IConvertible interface.

Do bear in mind that this isn't sophisticated enough to work with custom conversion rules or robust enough to deal with failure properly (beyond throwing an exception and making the entire operation fail). If you need support for this, provide an overload that accepts a TypeConverter or conversion delegate (as in mike z's answer).

Upvotes: 17

Mike Zboray
Mike Zboray

Reputation: 40828

There is no built in way to convert a string to an arbitrary type T. Your method would have to take some kind of delegate:

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

Upvotes: 9

p.s.w.g
p.s.w.g

Reputation: 149040

Seems like you could just use String.Split and Enumerable.Select?

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

But if you must make an extension, try this...

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

Upvotes: 6

Related Questions