2

I would like to create a function that will return list of type that is specified by me at run time. I tried something along this line:

  public static List<T> GetMyList<T>(string[] itemList)
  {
     List<T>  resultList = new List<T>(itemList.Length);
     return resultList.AddRange(itemList);
  }

But this doesn't work. Obviously I don't fully understand how to pass a type to be converted to. Any help would be appreciated it.

Edit: It looks like that it is not possible, but here is more info. String array will contain numbers and I would like to convert those numbers sometimes into int, sometimes into short. Idea behind is to have a generic function that will attempt to convert items into whatever type list I tell it.

2
  • 1
    Could you provide more information? What do the strings represent? Are they class names? Is it serialized information from type T? Commented Mar 5, 2010 at 18:53
  • 2
    How will the strings be converted to type T? Your function will need to get a Converter(of String, T) or Converter(of String(), T()) to make the conversion. Commented Mar 5, 2010 at 18:55

5 Answers 5

7

You need to provide a method to convert a string into a T - you can do this using a Func<string, T>:

public static List<T> GetMyList<T>(string[] itemList, Func<string, T> conversionFunc)
{
    return itemList.Select(conversionFunc).ToList();
}

e.g.

List<int> ints = GetMyList(new[] { "1", "2", "3" }, s => int.Parse(s));
Sign up to request clarification or add additional context in comments.

1 Comment

How about List.ConvertAll instead of writing a new function? Eg. string[] itemArray = { "1", "2" }; (itemArray.ToList()).ConvertAll((x) => int.Parse(x));
3

A slightly more elegant solution would be to add an extension method to string that automatically calls the parser for type T, like so:

public static class GenericParser {
    public static T Parse<T>(this string input) {
        var converter = TypeDescriptor.GetConverter(typeof(T));
        if ( converter != null ) {
            return ( T )converter.ConvertFromString(input);
        }
        return default(T);
    }
}    

Then, your conversion function would look something like:

public static List<T> GetMyList<T>(string[] itemList) {
    List<T> list = new List<T>();
    list.AddRange(Array.ConvertAll<string, T>(itemList, delegate(string s)  {
        return s.Parse<T>();
    }));
    return list;
}

And the usage would be:

List<int> integers = GetMyList<int>(new []{"1", "2", "3", "4"});
List<double> doubles = GetMyList<double>(new []{"1.0", "2.0", "3.0", "4.0"});

and so on.

Comments

1

My first thought is that this won't work because not every object type can be constructed from a string. Perhaps you want something with a signature more like:

public static List<T> GetMyList<T>(T[] itemList)
{
  List resultList = new List(itemList.Length);
  foreach (t in itemList)
  {
    resultList.add(t);
  }
  return resultList;
}

(forgive my syntax. I don't have a compiler handy right now to check it.)

Comments

0

this doesn't work because system has no idea how to convert string to generic T. Also even if it is known, it will not work, because C# (prior to 4) doesn't have type covariance. So use either foreach to copy and convert elements one by one or use Select from Linq

1 Comment

btw covariance works for arrays. but only if CLR can convert elements itseld, without conversion method
0

Similar to Lee's but more generic...

public static class Tools
{
    public static List<TResult> ToList<T, TResult>(
       this IEnumerable<T> input,
            Func<T, TResult> conversion)
    {
        return input.Select(conversion).ToList();
    }
    public static List<TResult> ToList<T, TResult>(
        this IEnumerable<T> input,
             Func<T, int, TResult> conversion)
    {
        return input.Select(conversion).ToList();
    }
}

class Program
{
    static void Main(string[] args)
    {
        var input = new[] { "1", "2", "3" };

        var ret = input.ToList(i => int.Parse(i));
        // 1,2,3

        var ret2 = input.ToList((i,j) => int.Parse(i) + j * 10);
        // 1,12,23
    }
}

1 Comment

I was a little surprised that an overload for .ToList<T>() didn't match the above signature.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.