2016-05-31 3 views
6

I持って(型オブジェクトの)値をとり、そうのようにint型とするuintのIEnumerableをにキャストしようとするいくつかのコード:IEnumerable <T>として値をキャストするのは、値をどのように初期化したかによって異なるのですか?

uint number = 1; 
object value = new []{ number }; 
:値がこのように初期化され

var idList = value as IEnumerable<int>; 
var uintList = value as IEnumerable<uint>; 

idListとuintListの両方に値がありますが、idList.ToList()を呼び出すとArrayTypeMismatchExceptionになります。ただし、値がnew List<uint>{ number }で生成される場合、idListは期待どおりにnullです。

さらに、VS2015の直下のウィンドウでvar idList = value as IEnumerable<int>;を呼び出すと、値がコレクション初期化子で生成された場合でも、期待通りにnullが返されます。

.Net fiddle reproducing the error here

ここでは何が起こっていますか?

+0

このスタックオーバーフローポストを見てください:http://stackoverflow.com/questions/7173266/casting-array-to-ienumerablet – DHP

+2

'value'を初期化しておけば' var idList = value私は実行時例外ではなくコンパイルエラーを返します。 –

+0

ここではコンパイルエラーはありませんが、コードパスを単純化する際に、値がキャストされる前にオブジェクト型にキャストされていたことがわかりました。 IEnumerableに戻る。それに応じて質問に追加します。ありがとうございます。 – RSid

答えて

3

このanswerに記載されているように、C#とCLRがintuintの間でどのように変換を処理するかが珍しいためです。最初にこのコードはコンパイルされないことに注意してください。

uint[] a1 = new[] { 1u }; 
var a2 = (int[])a1; 

C#ではキャストは存在しないと考えられているので注意してください。しかし、あなたはこの道を行く場合:私は答えにdesribedよう

uint[] a1 = new[] { 1u }; 
var a2 = (int[]) (object) a1; 

、このキャストが有効であるかどうランタイムが決定すると、それ(CLR)は、異なる考え、uint[]からint[]にキャストできます(およびその逆)リンクされた。

List<int>List<uint>についても同じことは成り立ちません。これらはCLRによって特別な方法で処理されないため、相互にキャストすることはできません。

は、だからあなたの場合には、uint[]int[]にキャストすることができ、あなたのidListがnullではないのでint[]は、IEnumerable<int>を実装しています。これはリストには当てはまらないので、あなたの問題です。 ToListメソッドは、最初のケースで失敗した理由については

、内部的にはそのような何かないので、それはです:1つの配列の要素のタイプならば、直接

uint[] a1 = new[] { 1u }; 
var a2 = (int[]) (object) a1; 
// ToList copies contents to new array 
int[] copy = new int[a2.Length]; 
Array.Copy(a2, copy, a2.Length); 

そしてArray.Copyチェックすると、別の配列の要素の種類と互換性があります。

+0

これは本当に奇妙です、説明のおかげで!私はCLRと言語がどちらにも同意しないとは思っていませんが、 – RSid

関連する問題