私は次のコードを持っています:
int intNumber1 = 100;
object intNumber2 = 100;
bool areNumberOfTheSameType = intNumber1.GetType() == intNumber2.GetType(); // TRUE
bool areEqual = intNumber1.Equals(intNumber2); // TRUE
long longNumber1 = (long) intNumber1; // OK
long longNumber2 = (long) intNumber2; // InvalidCastException. Why?
2番目のキャストが機能しないのはなぜですか?オブジェクトにlongへの明示的なキャストがないためか、実行時にそのタイプを見るとSystem.Int32
。
var
の代わりにdynamic
またはobject
を使用すると、機能します。
何かご意見は?
int
からlong
へのキャストは、2つのタイプ間の変換として解釈されます。
object
からint
へのキャストは、ボックス化されたint
のボックス化解除として解釈されます。
構文は同じですが、2つの異なることを述べています。
作業ケース(int
→long
、object
(boxed int
)→int
)では、コンパイラーはどのコードに作物。ボックス化されたint
→long
が機能する場合、コンパイラーはどの変換を使用するかを何らかの方法で判断する必要がありますが、それを行うための十分な情報がありません。
Eric Lippertからのこのブログ投稿 も参照してください。
object
は型int
を保持します。ただし、これはオブジェクト(ボックス化されたint)と見なされ、ボックス化された値の型は通常、その基になる型(ボックス化された型)にのみキャストできます。
それを別のタイプにキャストするには、まずそれをその基礎となるタイプにキャストする必要があります。これは機能します。
long longNumber2 = (long) (int) intNumber2;
var
が機能するのは、コンパイラがコンパイル時に型を推測するためです。つまり、var
を使用する場合、intNumber2
のタイプ(typeof
を使用する場合)はint
になります。 object
を使用する場合、タイプはobject
になります。
dynamic
の使用はまったく異なるプロセスであり、var
と比較することはできません。ここでは、リフレクションとDLRライブラリを使用して、変換/キャストが実行時に行われます。基になる型を動的に見つけ、変換演算子があり、それを使用します。
(注意:推測)
Int32
には、最初のキャストを実行したときに呼び出されるInt64
への変換演算子があります。 Object
はサポートしていません。そのため、2番目のキャストは、オブジェクトをスーパータイプではない別のタイプにキャストしようとしています(Int64
はInt32
を継承しません)。
var
で機能する理由は明白です。その場合、コンパイラーはint
を入力する手間を省きます。 dynamic
を使用すると、ランタイムは実行する必要があるすべての必要なチェックを行いますが、通常、コンパイラーはキャストを挿入するか、変換演算子を呼び出します。
2つの異なるタイプのキャスト(1つは変換、もう1つはボックス化解除)が原因で機能しないことは、ここの回答ですでに述べられています。便利な追加となる可能性があるのは、Convert.ToInt64()
が、longに変換できる組み込み型、またはIConvertible.ToInt64()
を実装するクラスの型のいずれかであるものを変換することです。ロングに。言い換えると、整数を含むオブジェクト(任意のサイズ)をlongにキャストできるようにしたい場合は、Convert.ToInt64()
が適しています。それはより高価ですが、あなたがやろうとしていることisキャストよりも高価であり、その違いは無視できます(オブジェクトがボックス化された長いものでなければならないことがわかっている場合、無駄になるほど大きい) 。
ボックス化されたのと同じタイプにボックス化解除する必要があります。
object intNumber2 = 100L;
// or value in the long type range
// object intNumber2 = 9223372036854775806;
long result = (long)intNumber2;