【问题标题】:C# casting to nullable type?C# 转换为可空类型?
【发布时间】:2012-04-21 08:50:13
【问题描述】:

超越CastAs之间的常规无聊区别

  • 如果我知道 apple 是一个Fruit,那么我可以使用(Fruit)apple - 如果它不是,它会抛出异常李>
  • as value 可以对照 null 检查是否成功[不会抛出异常...]

但是我一直在阅读 @EricLippert article 关于这个并且有一个关于 Nullable Value Types 的很​​好的示例:

short? s = (short?)123;
int? i = s as int?;

不会编译...

无法转换类型'short?'到'int?通过引用转换、装箱转换、拆箱转换、包装转换或空类型转换

很好。

为什么会这样:

    short? s = (short?)123;
    int? i = (int?)s;

是否编译? (违背所有期望!我知道s 不是int? - 它应该会爆炸,但它不是......)

这里的 Cast 检查应该比前一个例子(Bang)更致命

问起这个热门话题我感觉很糟糕。

提前致谢。

【问题讨论】:

  • 您准确地描述了 Eric Lippert 所写的内容 - 演员表会编译,而 as 运算符不会针对可空类型的情况。
  • @Yahia 但我们是否同意 short 不是 INT ?
  • short 不是 int 但可以强制转换/转换为 int - 这就是您要告诉编译器的内容:将此 short 设为 int。
  • 或者换句话说,在第一个示例中,s as int?,您正在尝试转换 s 本身。在第二个示例(int?)s 中,您获取s 并尝试转换它。这样有意义吗?
  • @RoyiNamir 尝试编译int i = 123 as int;,错误将是“as 运算符必须与引用类型一起使用('int' 是值类型)”。另一方面,int i = (int)123; 可以完美编译。

标签: c# .net-4.0 casting clr


【解决方案1】:

例子:

int? i = (int?)s;

编译器是否因为强制转换告诉编译器你知道一些它无法推断的东西,即s 可以转换为int?

如果转换不成功,您只会在运行时收到异常。

【讨论】:

  • @RoyiNamir - 抱歉,应该补充一点,以防万一演员表不起作用。
【解决方案2】:

我认为这是因为如果 as 失败,您将获得“有效”null 结果,因此误报。在第二种情况下,允许强制转换,因为如果失败,它将引发异常。

【讨论】:

    【解决方案3】:

    在您的第一个示例中,as 运算符尝试将对象s 用作int?。由于int? 不在short? 的继承链中,因此该操作失败。

    在您的第二个示例中,您实际上正在创建一个新的int? i,其值来自short? s。这是一个更慷慨的操作,因为它不必保留左侧的原始s 对象。

    这里的重点是as 不允许做任何不保留对象身份的事情。显式转换可以。

    以下是 C# 标准关于 (int?) 表单如何工作的说明:

    6.1.4 隐式可空转换

    对不可为空值进行操作的预定义隐式转换 类型也可以与这些类型的可为空形式一起使用。对于每个 预定义的隐式标识和转换的数字转换 从不可为空的值类型 S 到不可为空的值类型 T, 存在以下隐式可为空的转换:

    · 从 S 的隐式转换?到T?。

    · 从 S 到 T 的隐式转换?

    基于基础的隐式可为空转换的评估 从 S 到 T 的转换过程如下:

    · 如果可以为空的转换来自S?给T?:

    o 如果源值为 null(HasValue 属性为 false),则 结果是类型 T? 的空值。

    o 否则,转换被评估为从 S 的展开?到 S,然后是从 S 到 T 的基础转换,然后是 从 T 到 T 的包装(第 4.1.10 节)?

    · 如果可以为空的转换是从 S 到 T?,则转换 被评估为从 S 到 T 的基础转换,然后是 从 T 包装到 T?。

    【讨论】:

    • 除了这个解释之外,还有这行 (int?)s 确实与继承/拳击时代有关....但它有效,这是我不明白的事情。
    • @RoyiNamir,我不太明白。存在从shortint 的转换(在C、Java 和几乎所有其他地方都是如此),C# 规范描述了如何进行该转换并使其适用于可空类型。 (我在上面添加了相关摘录。)
    • @sblom 我认为你应该double-bold 上面的段落说The important point here is that as isn't allowed to do anything that doesn't preserve your object's identity. An explicit cast can. - 我认为这是核心。至于允许的铸造,我同意,这对我来说很清楚(as 不是真的),正如 Eric 所说,short-s 没有算术(这并不重要,但它更容易理解,我至少,转换),它转换为 int。
    • 实际上as int? 无法编译的原因是因为那不是一个有效的语法。 C# 不会尝试允许 as 具有可空值;编译器不会尝试使这样的转换成为可能。例如,我在想“我要么有一个 'boxed int',或者我希望结果变为 'null'”,但编译器不处理。
    【解决方案4】:

    原因是int?只是System.Nullable<int> 的简写(System.Nullable<T> 是类型)。 short 类型定义了对 int 的显式转换,但是 System.Nullable<T> 没有任何此类显式转换,因为 T 可以是任何其他值类型。

    【讨论】:

      【解决方案5】:

      我通过反射找到了这个可能的解决方案。 这个想法是:

          var notNullableValue = 3;
          var someNullableType = typeof(Nullable<int>);
          var nullableValue = Activator.CreateInstance(someNullableType, new[] { notNullableValue });
      

      在我的例子中,我不能使用直接转换,因为我使用任意类型和反射来创建对象并填充所有属性。

      【讨论】:

        猜你喜欢
        • 2022-01-22
        • 1970-01-01
        • 2014-11-21
        • 1970-01-01
        • 2017-01-11
        • 2019-07-18
        • 1970-01-01
        • 2015-11-01
        • 2015-11-17
        相关资源
        最近更新 更多