Jer*_*ell 27 c# unchecked-conversion
也许我是基础知识,但我还在学校学习这个C#的东西.据我所知,如果我将1加到最大值整数,哪一个是32位,结果将是负数.我读到C#提供了检查和未检查的关键字来处理溢出.已检查的关键字是一种东西,我发现它很有用,但未经检查的关键字怎么样?我真的找不到用于unchecked -keyworded块的有用的东西.有没有?接下来的两种方法如何相互不同?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Practice_6
{
class Program
{
static void Main(string[] args)
{
int value = Int32.MaxValue;
value++;
//Approach 1 to make a decision
if (value > Int32.MaxValue) {
//Do something
}
value = Int32.MaxValue;
//Approach 2 to make a decision
unchecked {
value++;
//Do something
}
//What's the difference between these two approaches to handle overflow?
}
}
Run Code Online (Sandbox Code Playgroud)
Eri*_*ert 41
更新:这个问题是我2015年4月的博客主题 ; 谢谢你有趣的问题!
你的第一个问题是:
该
checked关键字是有用的,但如何对unchecked关键字?我真的找不到它的用途.有没有?
C#设计团队不习惯添加对语言没用的功能.(除了一元加运算符之外,这是世界上最无用的运算符.)
unchecked关键字有两个主要用例.
首先,默认情况下始终检查常量整数运算.这可能很烦人.假设您有一些互操作代码,并且您希望为HRESULT E_FAIL创建一个常量:
const int E_FAIL = 0x80004005;
Run Code Online (Sandbox Code Playgroud)
这是一个错误,因为这个数字太大而不适合int.但你可能不想使用uint.你可能会想得很清楚我会说
const int E_FAIL = (int)0x80004005;
Run Code Online (Sandbox Code Playgroud)
但这也是非法的,因为默认情况下始终会检查包括转换在内的常量算法.
你要做的是关闭经过检查的常数运算
const int E_FAIL = unchecked((int)0x80004005);
Run Code Online (Sandbox Code Playgroud)
其次,C#中非常量整数数学的默认算法是未选中的,因为它更快,因为这是许多其他类似语言所做的.但是,C#允许您通过编译器标志将默认值更改为非常数整数数学的检查算术.如果您已经这样做了,并且需要暂时将其关闭,那么您必须使用unchecked块或表达式语法.
第三个用例是使用未经检查的块作为自我记录代码的一种形式,说"我知道我在这里做的操作可能会溢出,这对我没问题." 例如,我经常写一些类似的东西:
int GetHashCode()
{
unchecked
{
int fooCode = this.foo == null ? 0 : this.foo.GetHashCode();
int barCode = this.bar == null ? 0 : this.bar.GetHashCode();
return fooCode + 17 * barCode;
}
}
Run Code Online (Sandbox Code Playgroud)
"未经检查"向读者强调,我们完全期望乘法和添加哈希码可能会溢出,这是可以的.
你的第二个问题是:
这两种处理溢出的方法有什么区别?
好问题.
如果在您检查的上下文中,您的意思是:我希望算术总是在范围内; 如果不是那么我的程序有一个严重的错误,必须在它对世界造成更大的伤害之前终止,那么你根本不应该进行任何溢出检查,因为没有溢出.任何例外都应该终止程序; 选中的上下文只是让运行时确实能够验证代码的正确性.
如果在你检查的上下文中你的意思是我要求算术在边界内,但我从一个不值得信任的来源获得这些数据而且我懒得对它进行范围检查然后你应该捕获异常. 但是,更好的做法是进行范围检查,如果数据超出范围则提供更有意义的错误,而不是让运行时注意到问题并抛出溢出异常.我强烈建议进行范围检查而不是捕捉异常; 不要偷懒.
我不太确定checked和的性能影响unchecked.从理论上讲,unchecked应该是更高效的,它是默认的上下文.除非你为某种特殊的算法/业务逻辑等绕过整数类型的边界,否则checked很少使用/有用/可读.
正如我所说,unchecked是默认的上下文,为什么你需要一个unchecked关键字?有一点可能是明确上下文的类型,其中上下文的使用率很高checked.另一种是unchecked在checked上下文中使用上下文:
checked {
int a = 5 + 1231;
unchecked {
a += 221;
}
}
Run Code Online (Sandbox Code Playgroud)
您的问题可能是未选中默认上下文的原因.我想这是微软的设计选择.
它们的区别在于checked上下文检查每个算术运算是否存在溢出,如果存在溢出则引发异常.
正确编写的代码不应依赖于项目的编译默认为选中还是未选中。意外的包装算术行为可能对安全或系统稳定性造成风险的代码应在上下文中完成checked。依赖于包装算术行为的代码应该在unchecked上下文中完成。预计不会发生算术溢出但如果发生则后果有限的通用代码应使用项目级设置进行编译。然后,可以将项目级别设置设置为选中或取消选中,作为执行速度和及时错误捕获之间的权衡。
如果任何地方都没有发生意外溢出,代码将在未检查模式下运行得更快。但是,如果某些计算产生虚假值并且不清楚原因,则启用溢出检查重新编译可能会有所帮助。它会导致代码运行更慢,但会在第一次错误计算时陷入困境。然而,出于这种目的将项目切换到检查模式只有在项目中依赖于包装算术行为的部分在显式unchecked上下文中执行时才可能实现。否则切换项目级模式只会完全破坏程序。
| 归档时间: |
|
| 查看次数: |
10414 次 |
| 最近记录: |