开发者

C# - custom explicit conversion with checked/unchecked operator

I'm learning to write custom type conversions in C# and I have a question I can't manage to resolve with Google / MSDN / earlier posted SO items.

Normally, a C# program that narrows a numeric type does that via unchecked explicit conversion, e.g.:

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

however, the following will give an overflow exception:

byte b = checked((byte)i);

My question is as 开发者_StackOverflow中文版follows: is the behavior of the checked / unchecked keyword implementable in an custom type conversion, e.g.:

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

Of course, the code above is not the answer, but does anyone know if something like this is possible?


checked is a compile time thing. That is, its sole effect will be on the code block directly surrounded by a checked statement, not the methods called in that block. Consequently, there wouldn't be a checked and unchecked context at run time that you may want to adjust the behavior of a function according to it.


Section 14.5.12 of the C# language spec explicitly enumerates all the operators on which the checked and unchecked keywords can have an effect.

User defined operators are not part of that list, so no, you cannot write a user-defined conversion operator that takes checked/unchecked into account.


checked causes a "check for overflow" version of the appropriate CIL instruction to be generated by the compiler.

Here's a dump from IL Disassembler:

//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


Does it solve your problem to simply do this:

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


As I commented on some answers, I think I got the answer I was looking for. Controlling checked/unchecked explicit conversion behavior is only possible with "build-in numeric conversions" as far as I see.

Besides, it looks like unchecked conversion is evil, comsidering the strange results.


I think this can be done with a preprocessor directive. Just like you can say:

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

you could say:

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

But see /define (C# Compiler Options) for details on how to define such a symbol. It can be defined in the .csproj file.

Important: This approach is only useful to distinguish the situation where you change the global default overflow checking context, from the situation where you don't. There's no way you can tell if your explicit operator method was called from another method that used the checked/unchecked keyword, because as others have said, that checked/unchecked keyword is no longer in effect when control enters your method. At the entry of a method, the default overload checking context, as specified by compiler options or execution environment configuration, is in effect, and that's the context I'm suggesting you could detect with the preprocessor directive.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜