2015-11-24 6 views
20

これは.NETのバグかどうかわかりませんが、本当に面白いと思います。sbyte []は魔法のようにバイト[]にキャストできます

予想通り

、私はこれを行うことはできません。sbytesのタイプはobjectある場合

sbyte[] sbytes = { 1, 2, 3 }; 
byte[] bytes = sbytes; // fails: cannot convert source type 'sbyte[]' to taget type 'byte[]' 

しかし、これは動作します:1

object obj = new sbyte[]{ 1, 2, 3 }; 
byte[] bytes = obj as byte[]; 
Assert.IsNull(bytes, "WTF??") 

備考:同じ問題がint[]のために発生します - uint[]と他のプリミティブ型も同様です。

備考2:コードはbyte[]として配列を扱うが、デバッガは、フォーカスを失って、アレイ内の? -sを示します。

screenshot

備考3:これは配列のためではなく、根本的なタイプの自分自身のために働く:

object sbyteObj = (sbyte)1; 
byte byteObj = (byte)sbyteObj; // System.InvalidCastException: Specified cast is not valid. 

[OK]を、もちろん私はこのようなタイプを確認することができます。

if (obj.GetType() == typeof(byte[])) 

asオペレータとダイレクトキャストの意図した動作ですか、これは.NET bですug?

+0

これらの疑問符?私はこの行動を持っていません。最適化コードを無効にしてみてください。 –

答えて

26

いいえ、バグではありません。これは、C#言語ルール(変換が利用できないと主張する)とCLRルール(が利用可能なの変換)の間のインピーダンスの不一致に過ぎません。

コンパイラは本当に、本当に、それは最高のを知っていると考えていることを注意:

byte[] bytes = new byte[10]; 
// error CS0030: Cannot convert type 'byte[]' to 'sbyte[]' 
sbyte[] sbytes = (sbyte[]) bytes; 

そして、あなたは警告してコンパイルしたコードを持っている場合でも、それは実際にそれが言う何をしていません。

byte[] bytes = new byte[10]; 
// warning CS0184: The given expression is never of the provided ('sbyte[]') 
if (bytes is sbyte[]) 
{ 
    Console.WriteLine("Yes"); 
} 

実行するコードと、あなたはは、出力を得ることはありません...しかし、あなただけのbytesのコンパイル時の型を変更した場合、それ印刷はい行います

object bytes = new byte[10]; 
// No warning now 
if (bytes is sbyte[]) 
{ 
    Console.WriteLine("Yes"); // This is reached 
} 
+0

さて、 'is'、' as'と直接キャストは、少なくともプリミティブ型の配列ではなく、必ずしも信頼できるとは限りません。 – taffer

+0

@taffer:「必ずしも信頼できるとは限りません。それがコンパイル時にコンパイルされているのか、実行時に起こっているのかを知っていれば、何が起こるのかを正確に伝えることができます。 –

+0

フレームワークの小さなトリックを知っていれば、私はいつも何が起こるかを知ることができます。 :) Btw、私は、 'char'と' bool'を除き、 'IntPtr'と' UIntPtr'を含む、同じサイズのプリミティブ型のために症状が発生することを確認しました。私はあなたの答えの後でもこの行動を予測できたとは言いません。 – taffer

関連する問題