views:

663

answers:

5

I'm trying to cast List<object> to List<string> dynamically. I've tried several ways, but I can't find a solution. This is a small sample that shows the problem:

List<object> listObject = new List<object>();
listObject.Add("ITEM 1");
listObject.Add("ITEM 2");
listObject.Add("ITEM 3");

List<string> listString = ¿¿listObject??;

Thanks in advance!

+10  A: 

If you can use LINQ then the Cast method will do what you need:

List<string> listString = listObject.Cast<string>().ToList();

You can also use the ConvertAll method, as Stan points out in his answer:

List<string> listString = listObject.ConvertAll(x => (string)x);

If you're not using C#3 then you'll need to use the "old" delegate syntax rather than a lambda:

List<string> listString =
    listObject.ConvertAll(delegate(object x) { return (string)x; });
LukeH
+1 for correct use of delegate sytnax :)
Nader Shirazie
@nader: I always try to remember that when LINQ isn't available then neither is lambda syntax.
LukeH
+1 good point Luke
Stan R.
And just to pre-empt any nitpickers... I'm aware that VS2008 can target earlier versions of the .NET framework, which would allow the use of lambda syntax but not LINQ. But, as a rule-of-thumb, no LINQ usually means no lambdas too.
LukeH
+4  A: 

If you're using .NET 3.5 you can use, this way you don't have to do an extra ToList(). You can also supply your own converter if you need to convert advanced objects.

 List<string> listString = listObject.ConvertAll(x=> x as String);

If you can't use LINQ you can do this

foreach(object item in listObject)
{
  string convertedItem = item as String;
  if(convertedItem != null)
       listString.Add(convertedItem);
}
Stan R.
This is also supported in .NET 2.0 (without LINQ, though the delgate syntax is not as nice). One note though, I don't believe the .Cast<string>.ToList() will create an "extra" list as you're implying. It will create one new list, for the result, as does your approach
Nader Shirazie
I think you mean C# 3.0 and .Net 3.5.
sixlettervariables
that is what i meant. thanks.
Stan R.
@nader: I was implying that ToList() does an extra enumeration.
Stan R.
@Stan: Are you sure? ToList() will cause an enumeration, but that's it. Cast<string>() will not actually enumerate the collection.
Nader Shirazie
@Nader: I am pretty sure Cast enumerates it once to perform the cast on each object and then ToList does another enumeration I believe (it calls CopyTo)
Stan R.
@Stan: The `Cast` method just returns an iterator object which does nothing until you actually start enumerating the sequence (with `ToList`, `foreach` etc), at which point it casts and streams one element at a time. The sequence is only enumerated once.
LukeH
@Stan: Having said that, although both the "`Cast` then `ToList`" approach and the `ConvertAll` approach only enumerate the sequence once, I'd expect `ConvertAll` to be marginally quicker because it loops through the source `List`'s underlying array directly rather than using an iterator object. (Though I doubt if this difference would be noticeable in most real-world scenarios.)
LukeH
A: 

I don't think you can do it one step. Instead, try something like this:

  List<object> listObject = new List<object>();
  listObject.Add( "ITEM 1" );
  listObject.Add( "ITEM 2" );
  listObject.Add( "ITEM 3" );

  List<string> lstStr = new List<string>( listObject.Count );

  foreach ( object obj in listObject )
  {
   lstStr.Add( obj.ToString() );
  }
TLiebe
this is wrong, he doesn't want toc all ToString() on thos object, he wants to convert it to a string object. Technically your example will work this time, but only for strings. But if he happens to bump into a more advanced object, he wont be able to use this method.
Stan R.
It can be done in one step, see the other answers...
Nader Shirazie
A: 
List<string> listString = (from o in listObject select (string)o).ToList();
svinto
See `Enumerable.Cast<T>()`.
Pavel Minaev
A: 

How bout this:

public static List<T> ConvertToGenericList<T>(IList listOfObjects)
{
    List<T> items = new List<T>();

    for (int i = 0; i < listOfObjects.Count; i++)
    {
        items.Add((T)listOfObjects[i]);
    }
     return items;
}

Usage:

List<object> listObject = new List<object>();
listObject.Add("ITEM 1");
listObject.Add("ITEM 2");
listObject.Add("ITEM 3");
List<string> listString = Converter.ConvertToGenericList<string>(listObject);
Jon