48

I have a System.Array that I need to convert to string[]. Is there a better way to do this than just looping through the array, calling ToString on each element, and saving to a string[]? The problem is I don't necessarily know the type of the elements until runtime.

KrisTrip
  • 4,943
  • 12
  • 55
  • 74
  • Without knowing the types until runtime, you essentially need to iterate over the array (be it with LINQ or whatever method). – GrayWizardx Dec 28 '09 at 18:10

5 Answers5

73

How about using LINQ?

string[] foo = someObjectArray.OfType<object>().Select(o => o.ToString()).ToArray();
Craig Stuntz
  • 125,891
  • 12
  • 252
  • 273
  • I don't seem to have access to the .Select method from my Array. Am I missing something? – KrisTrip Dec 28 '09 at 18:18
  • 3
    Yes, add `System.Linq` to your `using` – Craig Stuntz Dec 28 '09 at 18:19
  • 1
    Make sure you are using C# 3, and that you've included the System.Linq namespace. – LBushkin Dec 28 '09 at 18:20
  • I have System.Linq in my using statements. Here is the error message I get: Error 1 'System.Array' does not contain a definition for 'Select' and no extension method 'Select' accepting a first argument of type 'System.Array' could be found (are you missing a using directive or an assembly reference?) – KrisTrip Dec 28 '09 at 18:23
  • 14
    @Craig, TheHurt, and LBushkin: `System.Array` doesn't implement `IEnumerable`, so most LINQ extensions won't work. There is, however, an `OfType` extension method on `IEnumerable` (which `System.Array` *does* implement), so it would have to be `string[] foo = someArray.OfType().Select(o=>o.ToString()).ToArray();`. – P Daddy Dec 28 '09 at 18:35
  • You also need `System.Collections.Generic` in your `using` for `IEnumerable`. – Craig Stuntz Dec 28 '09 at 18:38
  • Updated thanks to P Daddy; I forgot that `System.Array` is unusual. – Craig Stuntz Dec 28 '09 at 18:40
  • How would this be modified to ensure System.Array elements w/ null are maintained in the new string[]? – Chris Aug 31 '15 at 12:59
14

Is it just Array? Or is it (for example) object[]? If so:

object[] arr = ...
string[] strings = Array.ConvertAll<object, string>(arr, Convert.ToString);

Note than any 1-d array of reference-types should be castable to object[] (even if it is actually, for example, Foo[]), but value-types (such as int[]) can't be. So you could try:

Array a = ...
object[] arr = (object[]) a;
string[] strings = Array.ConvertAll<object, string>(arr, Convert.ToString);

But if it is something like int[], you'll have to loop manually.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • It is just Array and it could actually contain value types (probably will). – KrisTrip Dec 28 '09 at 18:37
  • @KrisTrip - the *variable* might be "just Array", but the object won't be; it has a definite array type. There is also a **big** difference between "contain value types" (which `object[]` can do), and "is a value-type array" (such as `int[]`). This difference matters in this case. Can you clarify what **exactly** the `Array` instance is? – Marc Gravell Dec 28 '09 at 19:04
  • I get the Array by using a ToArray method. I don't know until runtime but it could be an int[], double[], float[], string[], or Complex[] (user defined object) – KrisTrip Dec 28 '09 at 19:28
  • In that case, either you'll have to loop manually (like you are) or do some pretty messy reflection (`MakeGenericMethod`). The former would be preferable. – Marc Gravell Dec 28 '09 at 19:45
  • 1
    +1 for `object[] arr = (object[]) a;` as simple as it can be. – PCoder Feb 06 '13 at 13:51
4

You can use Array.ConvertAll, like this:

string[] strp = Array.ConvertAll<int, string>(arr, Convert.ToString);
Gabe
  • 84,912
  • 12
  • 139
  • 238
2

Simple and basic approach;

Array personNames = Array.CreateInstance(typeof (string), 3);
// or Array personNames = new string[3];
personNames.SetValue("Ally", 0);
personNames.SetValue("Eloise", 1);
personNames.SetValue("John", 2);

string[] names = (string[]) personNames; 
// or string[] names = personNames as string[]

foreach (string name in names)
    Console.WriteLine(name);

Or just an another approach: You can use personNames.ToArray too:

string[] names = (string[]) personNames.ToArray(typeof (string));
Umut D.
  • 1,746
  • 23
  • 24
0

This can probably be compressed, but it gets around the limitation of not being able to use Cast<> or Linq Select on a System.Array type of object.

Type myType = MethodToGetMyEnumType();
Array enumValuesArray = Enum.GetValues(myType);
object[] objectValues new object[enumValuesArray.Length];
Array.Copy(enumValuesArray, objectValues, enumValuesArray.Length);

var correctTypeIEnumerable = objectValues.Select(x => Convert.ChangeType(x, t));
bougiefever
  • 1,147
  • 10
  • 11