8

'object'型のフィールドがあります。Visual Studioのウォッチウィンドウ内でそれを調べると、そのObject []が表示され、要素にドリルダウンすると、各要素が文字列であることがわかります。

しかし、これをString []にキャストしようとすると、次のエラーが発生します。

'MyObject'(実際のタイプは'object []')を'string []'string[]にキャストできません

このキャストができない理由は何ですか?このオブジェクトを文字列配列に変換する最良の方法は何ですか?

4

6 に答える 6

23

これは、C#の特に紛らわしい機能です。これが取引です。

この説明全体を通して、配列の要素型は値型ではなく参照型であると想定しています。

C#は、安全でない配列共分散をサポートしています。つまり、文字列の配列がある場合、文字列をオブジェクトに変換できるため、それをオブジェクトの配列に変換できます。

string[] a1 = { "hello", "goodbye" };
object[] a2 = a1; // Legal

次に、a2から要素を取得しようとすると、次のように機能します。

object o3 = a2[0]; 

a2[0]は実際a1[0]には、オブジェクトに変換可能な文字列であるため、これは合法です。

ただし、配列に書き込もうとすると、実行時にエラーが発生します。

a2[0] = new object();

a2実際には文字列の配列であり、文字列以外の文字列を文字列の配列に入れることはできないため、これは実行時に失敗します。

したがって、C#はすでにひどく壊れています。コンパイルして正常に見えるプログラムを作成することは可能ですが、実際にはオブジェクトの配列ではないオブジェクトの配列にオブジェクトを配置しようとしたため、実行時に型例外で突然クラッシュします。

必要な機能はそれよりもさらに壊れており、C#はそれをサポートしていません。必要な機能は次のとおりです。

object[] a4 = { "Hello" };
string[] a5 = a4; 

それは安全でない配列の共変性です。それはこのようにひどく壊れます:

a4[0] = new Customer(); // Perfectly legal 
string s6 = a5[0]; 

そして今、Customerをstring型の変数にコピーしました。

いかなる種類の配列共分散または反変性も避ける必要があります。あなたが発見したように、配列の共変性は合法ではなく、配列の共分散はあなたのプログラムで予期せずに消える小さな時限爆弾を作っています。まず、適切なタイプの配列を作成します。

于 2012-04-13T14:59:25.920 に答える
17
string[] newarr =  Array.ConvertAll(objects, s => (string)s);

- 編集 -

あなたが私が持っているobjectobject[]と言ったので(それが実際にあることを知っている)

string[] newarr =  Array.ConvertAll((object[])objects, s => (string)s);
于 2012-04-13T14:10:37.457 に答える
0
object[] original = new object[]{"1", "2"};
//some code in between here
object obj = original ;
object[] objArray = (object[])obj;
string[] newArray = new string[objArray.Length];
for(int i = 0; i < newArray; i++)
{
  newArray[i] = (string)objArray[i];
}

ここでの他の答えは、変換を行うためのより速い/より短い方法を示しています。何が実際に起こっているのか、何が起こる必要があるのか​​を示しているので、私はこのようにすべてを書きました。実際の製品コードでは、より単純な方法の1つを使用する必要があります。

于 2012-04-13T14:12:23.913 に答える
0

オブジェクト指向プログラミングのルールは -

「派生クラスは常に基本クラスに型キャストできます」および「基本クラスが保持している現在のインスタンスが実際に派生クラスである場合にのみ、基本クラスを派生クラスにキャストできます」

例 (A はベース、B は派生)

A a = new B();  // legal;
B b = (B) a ;   // legal as "a" is actually B (in first statement)

違法 : >

A a = new A();
B b = (B) a;  // not legal as "a" is A only. 

同じことが Object クラスと String クラスに適用されます。オブジェクトは基底クラス、文字列は派生クラスです。

于 2012-04-16T04:31:39.677 に答える
-1

実数 string[]をに変換できますobject[]

これは配列の共分散です

リンクで明確な例を見つけることができます。

于 2012-04-13T14:12:16.037 に答える
-1

コレクション自体ではなく、コレクション内の各要素をキャストする必要があります。

object[] ovalues = new object[] { "alpha", "beta" };
string[] svalues = ovalues.Cast<string>().ToArray();
于 2012-04-13T14:12:49.980 に答える