質問

を持っています IDataRecord reader 次のように小数を取得しています。

decimal d = (decimal)reader[0];

何らかの理由で、これにより、「指定されたキャストは無効です」という無効なキャスト例外がスローされます。

私がする時 reader[0].GetType() それは Int32 であることがわかります。私の知る限り、これは問題ないはずです...

このスニペットでこれをテストしましたが、問題なく機能します。

int i = 3750;
decimal d = (decimal)i;

このため、リーダーに 10 進数として含まれる int をアンボックス化できないのはなぜかと頭を悩ませました。

なぜこれが起こるのか知っている人はいますか?何か微妙なところが欠けているのでしょうか?

役に立ちましたか?

解決

値型をボックス化解除して元の型 (およびその型の null 許容バージョン) にすることのみが可能です。

ちなみに、これは有効です (2 行バージョンの短縮形にすぎません)。

object i = 4;
decimal d = (decimal)(int)i; // works even w/o decimal as it's a widening conversion

この背後にある理由については、これをお読みください エリック・リッパートのブログエントリー:表現とアイデンティティ

個人的に、私はキャスト構文によって実行される処理を 4 つの異なるタイプの操作に分類します (これらはすべて異なる IL 命令を持ちます)。

  1. ボクシング (box IL 命令) と開梱 (unbox IL命令)
  2. 継承階層を介したキャスト (例: dynamic_cast<Type> C++ では、使用します castclass 確認するための IL 命令)
  3. プリミティブ型間のキャスト (例: static_cast<Type> C++ では、プリミティブ型間のさまざまな型のキャスト用の IL 命令が多数あります)
  4. ユーザー定義の変換演算子の呼び出し (IL レベルでは、それらは適切な関数への単なるメソッド呼び出しです) op_XXX 方法)。

他のヒント

がありintするdecimalをキャストには問題はありませんが、あなたがオブジェクトをアンボクシングされているときは、オブジェクトが含まれている正確な型を使用する必要があります。

int値にdecimal値をUnboxのために、あなたはまず、intとしてそれをUnboxの小数点にキャストします:

decimal d = (decimal)(int)reader[0];

IDataRecordインターフェースは、値をボックス化解除するためのメソッドがあります。

decimal d = (decimal)reader.GetInt32(0);

ここで簡単なソリューションです。それはアンボクシングの世話をして、小数点にキャスト。私のためにうまく働きました。

decimal d = Convert.ToDecimal(reader[0]);  // reader[0] is int

Mehrdad Afshariはそれを言っます:

  

あなたはその元の型への値の型(およびNULL可能にVHS版のみすることができます   そのタイプのバージョン)。

を実現する事はを鋳造し、アンボクシングの間に差があるということです。 jerryjvlは、優れた発言があった。

  

ある意味でそれはアンボクシングとキャスト構文的に見えることを残念です   同じ、彼らは非常に異なる操作なのでます。

鋳造ます:

int i = 3750; // Declares a normal int
decimal d = (decimal)i; // Casts an int into a decimal > OK

ボクシング/アンボクシングます:

object i = 3750; // Boxes an int ("3750" is similar to "(int)3750")
decimal d = (decimal)i; // Unboxes the boxed int into a decimal > KO, can only unbox it into a int or int?
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top