未检查的块对BigInteger不起作用
本文关键字:BigInteger 不起作用 检查 | 更新日期: 2023-09-27 18:06:44
刚才注意到未检查的上下文在处理BigInteger时不起作用,例如:
unchecked
{
// no exception, long1 assigned to -1 as expected
var long1 = (long)ulong.Parse(ulong.MaxValue.ToString());
}
unchecked
{
var bigInt = BigInteger.Parse(ulong.MaxValue.ToString());
// throws overflow exception
var long2 = (long)bigInt;
}
知道为什么会这样吗?大整数转换为其他基本整数类型的方式有什么特别之处吗?
谢谢,
c#编译器不知道BigInteger在逻辑上是"整型"。它只看到用户定义的类型,用户定义的类型显式转换为long。从编译器的角度来看,
long long2 = (long)bigInt;
与
完全相同long long2 = someObject.SomeMethodWithAFunnyNameThatReturnsALong();
它无法到达该方法内部并告诉它停止抛出异常。
但是当编译器看到int x = (int) someLong;
编译器生成进行转换的代码,因此它可以选择生成它认为合适的检查或未检查的代码。
记住,"选中"answers"未选中"在运行时没有影响;当控件进入未检查的上下文时,CLR不会进入"未检查模式"。"checked"answers"unchecked"是对编译器的指令,指示在块中生成哪种代码。它们只在编译时起作用,并且BigInt转换为long的编译已经发生了。它的行为是固定的
OverflowException
实际上是由在BigInteger
上定义的显式强制转换操作符抛出的。它看起来像这样:
int num = BigInteger.Length(value._bits);
if (num > 2)
{
throw new OverflowException(SR.GetString("Overflow_Int64"));
}
换句话说,它以方式处理溢出,而不管checked
或unchecked
上下文的。医生是这么说的
更新:当然,Eric是这个问题的最终定论。请去看他的帖子:)
文档明确指出在这种情况下它将抛出OverflowException
。被检查的上下文只对c#编译器发出的"本地"算术运算有影响——不包括调用显式转换操作符。
要"安全地"执行转换,您必须首先将其与long.MaxValue
和long.MinValue
进行比较,以检查它是否在范围内。为了获得溢出到负的效果,我怀疑您必须首先在BigInteger
中执行use位操作符。例如:
using System;
using System.Numerics;
class Program
{
static void Main(string[] args)
{
BigInteger bigValue = new BigInteger(ulong.MaxValue);
long x = ConvertToInt64Unchecked(bigValue);
Console.WriteLine(x);
}
private static readonly BigInteger MaxUInt64AsBigInteger
= ulong.MaxValue;
private static long ConvertToInt64Unchecked(BigInteger input)
{
unchecked
{
return (long) (ulong) (input & MaxUInt64AsBigInteger);
}
}
}