C# - 使用checked / unchecked运算符进行自定义显式转换

时间:2009-11-12 17:52:55

标签: c#

我正在学习使用C#编写自定义类型转换,我有一个问题我无法通过Google / MSDN /早期发布的SO项目解决。

通常,缩小数字类型的C#程序通过未经检查的显式转换来实现,例如:

int i = 256;
byte b = (byte)i; // b == 0

但是,以下内容会产生溢出异常:

byte b = checked((byte)i);

我的问题如下:在自定义类型转换中可实现的checked / unchecked关键字的行为,例如:

class Foo {
  public static explicit operator int(Foo bar) {
    if (checked)
      throw someEception
    else
      return some Foo to int conversion
  }
}

当然,上面的代码不是答案,但有人知道这样的事情是否可行?

6 个答案:

答案 0 :(得分:6)

checked是编译时间的事情。也就是说,它的唯一影响将是由checked语句包围的代码块直接,而不是该块中调用的方法。因此,运行时不会出现checkedunchecked上下文,您可能希望根据它调整函数的行为。

答案 1 :(得分:5)

C#语言规范的

Section 14.5.12明确枚举了已检查和未检查的关键字可以生效的所有运算符。

用户定义的运算符不属于该列表的一部分,因此不能编写用户定义的转换运算符,该运算符将已选中/取消选中。

答案 2 :(得分:4)

checked导致编译器生成相应CIL指令的“检查溢出”版本。

这是来自IL反汇编程序的转储:

//000012:       Int32 i = 42;
  IL_0001:  ldc.i4.s   42
  IL_0003:  stloc.0
//000013:       Byte b1 = (Byte) i;
  IL_0004:  ldloc.0
  IL_0005:  conv.u1
  IL_0006:  stloc.1
//000014:       Byte b2 = checked ((Byte) i);
  IL_0007:  ldloc.0
  IL_0008:  conv.ovf.u1
  IL_0009:  stloc.2

答案 3 :(得分:0)

只是这样才能解决您的问题:

class Foo {
  public static explicit operator int(Foo bar) {
    unchecked {
      return some Foo to int conversion
    }
  }
}

答案 4 :(得分:0)

当我评论一些答案时,我想我得到了我正在寻找的答案。只有在我看到的情况下,才能通过“内置数字转换”来控制已检查/未检查的显式转换行为。

此外,看起来未经检查的转换是邪恶的,考虑到奇怪的结果。

答案 5 :(得分:0)

认为这可以通过预处理器指令完成。就像你可以说:

#if DEBUG
        Console.WriteLine("This code is only compiled in debug mode");
#else
        Console.WriteLine("This code is only compiled in release mode");
#endif
你可以说:

#if CHECKED
        // code here to be compiled only if "checked" is the default overflow checking context
#else
        // code for "unchecked"
#endif

但请参阅/define (C# Compiler Options)了解有关如何定义此类符号的详细信息。它可以在.csproj文件中定义。

重要提示:此方法仅用于区分更改全局默认溢出检查上下文的情况与不更改全局默认溢出检查上下文的情况。如果您使用explicit operator / checked关键字的其他方法调用了unchecked方法,则无法判断,因为正如其他方法所说,checked / {{当控件进入您的方法时,1}}关键字不再有效。在方法的入口处,由编译器选项或执行环境配置指定的默认重载检查上下文生效,这是我建议您可以使用预处理器指令检测的上下文。