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?
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>(";");
Extension methods are defined as static methods but are called by using instance method syntax. Their first parameter specifies which type the method operates on. The parameter is preceded by the this modifier.
In C#, the extension method concept allows you to add new methods in the existing class or in the structure without modifying the source code of the original type and you do not require any kind of special permission from the original type and there is no need to re-compile the original type.
To convert a delimited string to a sequence of strings in C#, you can use the String. Split() method. Since the Split() method returns a string array, you can convert it into a List using the ToList() method.
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).
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();
}
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));
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With