我创建了以下属性,它引发了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,但我觉得可能是在逻辑缺陷。我会离开它作为一个练习读者指出的缺陷。

因为我已经改变了属性来读取

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索引器的返回类型为Object(我假设你的意思是ASP.NET视图状态在这里)。现在考虑什么样的编译器有它看到这个的时候(这相当于你的代码)做:

object o = ViewState[...];
var x = o ?? -1;

它具有以某种方式推断表达o ?? -1的结果类型。在左边它看到一个object,右边是一个int。显然,对于这种表达最一般的类型也object。然而,这意味着,如果它实际上结束了使用-1(因为o为空)时,它必须把它转换为object - 以及用于int,这意味着拳击

所以x的类型是object的,并且它可以包含一个int(也许还有一些其他的整数类型 - 我们不知道什么是在你的浏览状态,它可以被short,例如)。现在,你写的:

long y = (long)x;

由于xobject,这是取消装箱。然而,你只能拆箱值类型为类型完全相同的(唯一的例外是,你可以替代等效的无符号类型作为它的底层基类型有符号类型和enum)。也就是说,你不能拆箱intlong。一个简单得多的方式来摄制,既没有“额外”的代码,将是:

object x = 123;
long y = (long)x;

其中也抛出InvalidCastException,以及用于精确相同的原因。

其他提示

一个铸造必须是唯一的一个步骤。

在表达式<object> ?? <int>会产生另一个对象,并且当所述第一值为空,即。 ViewState[TOTAL_RECORD_COUNT]为空,然后将所得的值将是一个对象,具有一个装箱的Int32在它

由于不能拆箱含有一个Int32到长的对象,则需要首先将其拆箱为Int32,然后将其转换为长。

在问题不是ViewState[TOTAL_RECORD_COUNT]的开箱,问题是-1的装箱和取消装箱。

   ViewState[TOTAL_RECORD_COUNT] ?? -1

您正在使用??运营商“对象”和“INT”上。将得到的类型是“对象”。这意味着-1将盒装(如INT)当该字段不视图状态存在。

然后程序崩溃后,当它试图拆箱(INT)-1作为长。

在你原来的,如果你打破它,你正在做的:

(ViewState[TOTAL_RECORD_COUNT] ?? -1)

空合并运算符(?)是specifially设计成:

  

,以限定用于的空值类型以及<强>引用类型的默认值。

在你的情况,你用它来处理一个System.Object,所以要采取你的“-1”,把它作为一个Int32,和盒子到一个新System.Object的。然后,尝试将的Int32拆箱成长,这将失败,因为铸造不能拆箱和在单一步骤中改变的类型。

可以通过指定的-1是一个长期通过使用L后缀容易解决这个问题:

public long TotalRecordCount
{
    get { return (long)(ViewState[TOTAL_RECORD_COUNT] ?? -1L); }
    set { ViewState[TOTAL_RECORD_COUNT] = value; }
}

的Int64 是值类型,所以铸造null值类型总是会抛出异常(NullReferenceException)。铸造一个Int32到Int64的会成功,会不会引发InvalidCastException

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top