web-dev-qa-db-ja.com

文字列配列のオブジェクト

オブジェクト(ここでは 'obj'として宣言されています:オブジェクトは配列、プリミティブ)を文字列配列に変換しようとしています。

オブジェクトには、uint []、int16 []などを指定できます。

私は使用しようとしています

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

この問題は、不明なタイプのオブジェクトをobject []にキャストしようとすると発生します。キャストエラーが発生しました。

私が試みた1つの試みは失敗しました

object[] arr = (object[])obj;

または

IEnumerable<object> list = obj as IEnumerable<object>
object[] arr = (object[])list;

キャストに関する値型と参照型の問題に関する投稿を見ました。

配列である限り、オブジェクトのタイプに関係なくobject []へのキャストを処理できる単純なコードはありますか?すべての可能な型キャストの手動処理を回避しようとしています。

前もって感謝します

45
swcraft

すべての配列がIEnumerableを実装するという事実を使用できます。

string[] arr = ((IEnumerable)obj).Cast<object>()
                                 .Select(x => x.ToString())
                                 .ToArray();

これにより、プリミティブを文字列に変換する前に適切にボックス化されます。

キャストが失敗する理由は、参照タイプの配列は共変ですが、タイプの配列は共変ではないためです。

object[] x = new string[10]; // Fine
object[] y = new int[10]; // Fails

ただし、IEnumerableのみにキャストしても機能します。必要に応じて、Arrayにキャストできます。

73
Jon Skeet

常に何らかのタイプ(配列、リストなど)のコレクションである場合は、単純な古いSystem.Collections.IEnumerableそしてそこから行く

string[] str = ((System.Collections.IEnumerable)obj)
  .Cast<object>()
  .Select(x => x.ToString())
  .ToArray();

以下は、非コレクションも処理するより徹底的な実装です。

static string[] ToStringArray(object arg) {
  var collection = arg as System.Collections.IEnumerable;
  if (collection != null) {
    return collection
      .Cast<object>()
      .Select(x => x.ToString())
      .ToArray();
  }

  if (arg == null) {
    return new string[] { };
  }

  return new string[] { arg.ToString() };
}
12
JaredPar