質問
私はInvalidCastException
がViewState[TOTAL_RECORD_COUNT]
たときにゲッターがアクセスされた場合null
を投げた次のプロパティを作成します。
public long TotalRecordCount
{
get { return (long)(ViewState[TOTAL_RECORD_COUNT] ?? -1); }
set { ViewState[TOTAL_RECORD_COUNT] = value; }
}
私の考えは、それは間違ってそれがViewState[TOTAL_RECORD_COUNT]
が含まれているため失敗したint
にlong
内のオブジェクトをVHS版しようとしたことですが、私はそのロジックに欠陥があるかもしれないと思います。私はその欠陥を指摘する読者への課題として、それを残してます。
私は以来、プロパティは読み取りにすることを変更しました。
public long TotalRecordCount
{
get { return (long?)ViewState[TOTAL_RECORD_COUNT] ?? -1; }
set { ViewState[TOTAL_RECORD_COUNT] = value; }
}
これだけ膨潤動作します。それでも、私は左の私の元のバージョンで間違っていたものを疑問に思って... StackOverflowの救助に?
私はイミディエイトウィンドウに(long)(ViewState[TOTAL_RECORD_COUNT] ?? -1)
を実行しようとすると、私はエラーメッセージCannot unbox 'ViewState[TOTAL_RECORD_COUNT] ?? -1' as a 'long'
を取得し、私は(ViewState[TOTAL_RECORD_COUNT] ?? -1).GetType().Name
を実行する場合、私はInt32
を得ることに注意してください。私は(long)-1
を実行し、で終わることができます-1 Int64
として...次第ですので、何?
解決
ViewState
インデクサの戻り値の型は(私はあなたがここにASP.NETのビューステートを意味すると仮定)Object
です。今コンパイラが、それは(あなたのコードに相当する)これを見ているときに実行しているかを検討します:
object o = ViewState[...];
var x = o ?? -1;
これは、何らかの形で表現o ?? -1
の結果の型を推論する必要があります。それはobject
を見て左側には、右側にint
です。明らかに、この表現のための最も一般的なタイプもobject
です。しかし、これは(-1
がNULLであったため)、それが実際にそのo
を使って終了した場合、それはobject
に変換しなければならないことを意味します - 。とint
のために、これはボクシングを意味します。
だから、x
はタイプobject
のものであり、それはint
が含まれていてもよい(そしておそらくまた、いくつかの他の整数型 - 私たちはあなたのビューステートにあるかわからない、それは例えば、short
することができます)。今、あなたは書きます:
long y = (long)x;
x
がobject
あるので、これはアンボクシングされます。ただし、缶(あなたは、その下地の種類のための符号付き等価unsigned型の型、および列挙を置き換えることができることのみを除いて)全く同じタイプにのみVHS版値型。それはあなたがint
にlong
をUnboxのことはできません。これをREPROするはるかに簡単な方法は、ない「余分な」コードで、次のようになります。
object x = 123;
long y = (long)x;
またInvalidCastException
をスローし、まったく同じ理由でます。
他のヒント
キャストは1つのステップのみである必要があります。
、すなわち、発現<object> ?? <int>
は、別のオブジェクトを生成し、最初の値がヌルである場合。 ViewState[TOTAL_RECORD_COUNT]
がnullである場合、結果の値は、それに箱入りのInt32と、オブジェクトになります。
は、最初のInt32にそれをUnboxの、そして長いにキャストする必要があります。
問題は、問題が-1のボクシングとアンボクシングされ、ViewState[TOTAL_RECORD_COUNT]
のアンボクシングではありません。
ViewState[TOTAL_RECORD_COUNT] ?? -1
あなたは使用しています? 「オブジェクト」と「INT」のオペレーター。得られたタイプが「オブジェクト」です。このフィールドは、ビューステートに存在しない場合に-1を(intとして)ボックス化されることを意味します。
それは(int)をVHS版しようとすると、次に、あなたのプログラムは、後にクラッシュ-1限ります。
あなたはそれを打破する場合は、あなたの元には、あなたがやっていた。
(ViewState[TOTAL_RECORD_COUNT] ?? -1)
ヌル合体演算子(??)specifiallyあるの設計されます:
の null許容値型のと同様の参照型のデフォルト値を定義する。の
あなたのケースでは、あなたがたSystem.Objectを処理するためにそれを使用しているので、あなたの「-1」を取るのInt32として扱い、そして新しいのSystem.Objectにそれを箱になるだろう。キャストは、単一のステップで種類をVHS版と変更することはできませんので、次に、それは、失敗した、長いへのInt32をVHS版しようとします。
あなたは-1がLの接尾辞を使用しての長さであることを指定することで、簡単にこの問題を解決することができます:
public long TotalRecordCount
{
get { return (long)(ViewState[TOTAL_RECORD_COUNT] ?? -1L); }
set { ViewState[TOTAL_RECORD_COUNT] = value; }
}
のInt64 のようnull
を鋳造、値型であります値型に常に例外(NullReferenceException
)をスローします。そして、Int64型へのInt32をキャストすることは成功するとInvalidCastException
をスローしません。