2012-04-13 8 views
8

私はタイプ 'オブジェクト'のフィールドを持っています。私がVisual Studioの[ウォッチ]ウィンドウでそれを調べると、Object []が表示され、要素にドリルすると、各要素が文字列であることがわかります。オブジェクト(本当にオブジェクト[])を文字列[]に変換できないのはなぜですか?

しかし、私は文字列にこれをキャストしようとすると、[]私はこのエラーを取得する:

Cannot cast 'MyObject' (which has an actual type of 'object[]') to 'string[]' string[]

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

+0

どのように配列をキャストしていますか?全体として?配列のすべての要素を個別にキャストする必要があります。 – Msonic

+0

はい、彼は明らかにそれを全体としてキャスティングしています。 –

+1

参照配列の分散は逆です。 **実際には 'string []'を 'object []'としてキャストできますが、それは実際に 'string []'でなければなりません。 –

答えて

16
string[] newarr = Array.ConvertAll(objects, s => (string)s); 

--EDIT--

あなたが言ってきたので、私はあなたが本当のを変換することができます(それは実際にobject[]であることを知っている)object

string[] newarr = Array.ConvertAll((object[])objects, s => (string)s); 
+0

これはコンパイルされていないようです。 。私はエラーが発生しています:型推論を推論することはできません。 。 。 – leora

+0

@leora更新された回答を参照してください。 –

-1

を持っていますstring[]~object[]

これはArray covariance

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

+0

@downvoter:説明する気に? – Tigran

+0

私のd/vではなく、おそらくb/cには –

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つを使用する必要があります。

+0

の例が含まれていませんでした。 。何らかの理由であなたのソリューションが私のためにコンパイルされて動作する唯一のソリューションです。 。 – leora

+0

@leoraほとんどの人が問題の一部を解決しましたが、全体的な問題は解決しませんでした。彼らはその部分をよりきれいに/エレガントに解決しました。私が言ったように、このコードは、あなたのためにその半分を行うライブラリメソッドがあっても、何が起こる必要があるかを示すように設計されています。 – Servy

+0

@Servy 'しかし全部ではありませんね? –

-1

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

object[] ovalues = new object[] { "alpha", "beta" }; 
string[] svalues = ovalues.Cast<string>().ToArray(); 
+0

私はオブジェクト[]を持っていません。 .iはオブジェクトしか持っていません。 。私が「キャストを解決できません」ということを考えれば、 – leora

+0

@leora 'System.Linq; –

+0

hmmを使用しています。 。 。私はすでにその参照を持っています。 。 。 – leora

23

これはC#の特に混乱する機能です。ここでは取引があります。

ここでは、配列の要素型が値型ではなく参照型であると仮定します。

C#サポート安全でない配列の共分散。それはあなたが、文字列の配列を持っている場合は、文字列をオブジェクトに変換することができますので、あなたは、オブジェクトの配列に変換することができることを意味:あなたはその後、A2のうちの要素を取得しようとした場合

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

、それは動作します:a2[0]オブジェクトに変換可能な文字列であり、これは、本当にa1[0]であるため、法的です

object o3 = a2[0]; 

を。あなたは、あなたが実行時時にエラーを得るでしょうアレイへ書き込みしようとすると

はしかし、:

a2[0] = new object(); 

a2が本当に文字列の配列あるので、これは、実行時に失敗しました非文字列を文字列の配列に入れることはできません。

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

あなたが望む機能は、よりもさらに壊れていて、より壊れていて、ありがとうC#はサポートしていません。あなたが欲しい機能がある:危険な配列contravarianceだろう

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

。それはこのように恐ろしく破る:

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

そして今、我々はちょうどタイプ文字列の変数にカスタマーをコピーしました。

どのような種類の配列の共分散または反分散を避ける必要があります。あなたが発見したように、配列の反動は法的ではなく、配列の共分散は予期せずに消えてしまうあなたのプログラムにはほとんど時間の爆弾を作りません。 正しいタイプの配列を最初に作成します。

+1

私はあなたが言うことの大部分に同意しますが、配列の反復性は配列の共分散よりも壊れています - 完全に二重の状況のように見えます。配列の反分散を使用すると、オブジェクト配列を介して別の型のオブジェクトがその場所に書き込まれていない限り、オブジェクト配列を読み書きし、文字列配列に書き込んだり、文字列配列から読み込んだりすることができます。共分散を使用すると、文字配列を読み込み、オブジェクト配列から読み込んだり、その位置に文字列を挿入している限り、オブジェクト配列に書き込むことができます。 – kvb

+4

@kvb:あなたの意見を取ります。私は共変の場合、壊れたシナリオが変換に追いついて失敗するため、「もっと壊れている」と言います。しかし、多くの人が配列を*効果的に*読み込み専用配列として使用するため、配列が作成されたときにのみ書き込みます。変換後には書き込みが行われず、変換後には読み込みのみが行われます。つまり、変換後に*書き込み*があった場合にのみ*破損することができます。しかし、逆変わる場合は、変換後に読み込まれた*すべての*を破ることができます。配列がすべての文字列で始まっていない可能性があります。 –

0

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

AND 「基本クラスは、派生クラスにキャストすることができる「派生クラスは常に型が基本クラスにキャストすることができる」だけ現在のインスタンスその基底クラス保持している場合オフは実際にクラス "

違法

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

(Aはベースであり、Bが導出される):>

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

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

関連する問題