views:

878

answers:

7

I am looking for a one liner that transforms List<T> into object[]. It's one liner, so I am not interesting in solutions such as foreach, or for...

Any takers?

Hint: No, both List<T>.ToArray() and List<T>.ToArray<object>() don't work.

Edit: Why List<T>.ToArray<object>() doesn't work? Because it can't compile.

+16  A: 
mylist.Cast<object>().ToArray()

That will only iterate once, by the way, in case you were wondering about the performance. O(n). :)

Why? Well, because Cast<object> will use deferred execution and won't actually do anything until the list is iterated by ToArray().

Edit: Alternatively, you could use LINQ to do the same thing in one line with one iteration:

var myObjectArray = (from item in myList select item as object).ToArray();

The first is probably easier to understand and type, but the second is much more fun, because, hey, it's LINQ!

Randolpho
Didn't see the generic argument on the cast, so I posted another answer. This is the right answer. +1
Stefan Steinegger
Both are LINQ. Second one is a LINQ query.
Samuel
@Samuel: very true. :)
Randolpho
+2  A: 
theList.Cast<object>().ToArray()

or

new List<object>(theList).ToArray()
Stefan Steinegger
Your first is preferrable. Your second option will iterate over the list twice. Cast<object> will not actually iterate over the list.
Randolpho
@Randolpho, correct me if I'm wrong, but ToArray has to traverse the list in order to create an array. The casting is deferred until this occurs, but since it happens on the same line, it's effectviely iterating the entire list. Option 2, however does look like it would iterate twice.
Michael Meadows
@Michael: That's what he said. The second would iterate twice.
Samuel
@Stefan: The second will iterate twice because the List constructor will iterate over the original list to build its internal array. Then the ToArray() call will iterate over it to transform it to an array. You may be thinking that ToArray will return the List's internal array, but this is not the case. See http://msdn.microsoft.com/en-us/library/x303t819.aspx for details
Randolpho
@Samuel, I was agreeing with the assessment that option two iterates twice, but questioning the assertion that Cast<object> will not iterate. While that statement in isolation is true, it might lead people to believe that there's no iteration. I don't think that's what @Randolpho was trying to say, but it just appears to say it. I was just looking for clarification.
Michael Meadows
@both: My apologies for the miscommunication. To be clear: The first option will iterate once, because the call to ToArray() will iterate over the enumeration, but the call to Cast<object>() will not iterate, as it uses deferred execution. See my answer for a link explaining how that works. The second option will iterate twice because the List constructor will iterate during construction, and the ToArray() call will iterate a second time to build the array.
Randolpho
Hm, I never tired to propose the most optimized solution, but the most readable or intuitive. Things that people understand and can remember are also important.
Stefan Steinegger
@Stefan Steinegger, the easiest to read and maintain should always be the first solution, but it's also important to understand the performance implications of your algorithms. That way, if it does become a performance bottleneck, you know exactly why, and have alternatives ready. Also, if you have two relatively equatable solutions available (as above), performance may be the deciding criterion.
Michael Meadows
@Michael: I agree. The only reason why I also proposed the other was the fact that some people don't know / use Link. It's the "old school" style which even a C# beginner should understand.
Stefan Steinegger
+1  A: 

If you don't mind writing a very short, reusable function, the ConvertAll Extension Method might help:

http://msdn.microsoft.com/en-us/library/73fe8cwf.aspx

EDIT:

This would work too

List<int> intList = new List<int>() { 1, 3, 4 };
object[] objectList = intList.ConvertAll(item => (object)item).ToArray();
Pwninstein
Why? If all he needs is object[], then .Cast<object>() is perfect.
Samuel
+4  A: 
List<T>.Select(x => x as object).ToArray();

Should return an object[].

çağdaş
ooh, that gives me an idea...
Randolpho
+2  A: 
And for a pre-LINQ solution (that only works for reference types).
(object[])List<T>.ToArray();
Samuel
You don't need the cast, reference types are all objects anyway.
Stevo3000
@Stevo3000 he certainly does need the cast, since that's a requirement of the original question. Casting to an array of objects.
Randolpho
@Randolpho - Not true, all reference types are objects. Just because the question asks for a cast does not mean it is required. Any reference type can be stored as an object.
Stevo3000
A: 

In C# on .NET 2.0 (VS 2008) the following compiles and doesn't use LINQ (as far as I can see) for reference types.

 object[] oArray;
 List<MyObject> oList = new List<MyObject>();
 oArray = oList.ToArray();

This does not require a cast as all reference types have object as their base.

Stevo3000
It does not compile on my machine: VS 2008, .net 3.5
Ngu Soon Hui
@Ngu Soon Hui - Did you make sure that you were using a reference type? It compiles perfectly on my VS 2008 machine as .NET 3.5.
Stevo3000
+1  A: 

If you don't have Linq (.Net 3.0) then you can use the ConvertAll() and ToArray() methods in List:

List<T> list = new List<T>();

object[] objects = list.ConvertAll<object>(item => (object)item).ToArray();
jrummell