在C ++中,有很多方法可以编写编译的代码,但会产生undefined behavior (Wikipedia)。 C#中有类似的东西吗?我们可以用编译的C#编写代码,但是有不确定的行为吗?
答案 0 :(得分:37)
正如其他人所提到的,“不安全”块中的任何内容都可以产生实现定义的行为;滥用不安全的块允许您更改构成运行时本身的代码字节,因此所有的赌注都会关闭。
整数除法的极端情况具有实现定义的行为。
抛出异常并且永远不会捕获它会导致实现定义的行为 - 终止进程,启动调试器等等。
在C#中还有许多其他情况,我们被迫发出具有实现确定行为的代码。例如,这种情况:
http://blogs.msdn.com/ericlippert/archive/2006/04/06/odious-ambiguous-overloads-part-two.aspx
但是,安全,行为良好的C#程序具有实现定义行为的情况应该非常少见。
答案 1 :(得分:27)
是的!即使在安全的背景下,也有! (好吧,它的实现定义为未定义,至少)
这是来自Roslyn issues的Marek Safar和VSadov的一个。关于bool
,C#和CLI之间存在不匹配。
C#认为只有一种true
和一种false
。
CLI认为false
是一个包含0的字节,其他所有值都是true
。
这种差异意味着我们可以强迫C#做一些(略微)有趣的事情事情:
//non-standard bool
//We're setting a bool's value to a byte value of 5.
var a = new bool[1];
Buffer.SetByte(a, 0, 5);
//non-standard bool
//We're setting a bool's value to a byte value of 10.
var b = new bool[1];
Buffer.SetByte(b, 0, 10);
//Both are true.
Console.WriteLine(a[0]);
Console.WriteLine(b[0]);
//But they are not the same true.
Console.WriteLine(a[0] == b[0]);
以上输出:
true
true
false
有趣的是,调试器不同意(必须以不同的方式评估真相?)
无论如何,C#团队似乎已经得出结论(重点补充):
即。语言将完全不关心非标准的bool。特定实现(如在CIL上的MS C#中)将确认非标准bool的存在并将其行为指定为 undefined
答案 2 :(得分:13)
查看Wiki,不允许发生未定义行为的情况或在C#中抛出异常。
但是在不安全的代码中,我认为未定义的行为是可能的,因为它允许你使用指针等。
编辑:看起来我是对的:http://msdn.microsoft.com/en-us/library/aa664771%28VS.71%29.aspx
在c#
中有一个未定义行为的示例答案 3 :(得分:11)
根据ECMA-334文件(第473页):
不包含任何内容的程序 出现不安全修饰符 不能展示任何未定义的 行为。
这促使'实施定义'到最坏的情况,请参阅Eric Lippert的回答。
答案 4 :(得分:1)
许多和子程序的要求可以概括为:
给定有效数据时,生成有效输出。
即使给予无效输入,也不要发射核导弹或否定时间和因果律。
Java和.NET语言的主要设计目标之一是,除非代码使用标记为"不安全的某些内容,否则通常不需要特别的努力来满足上面的第二个约束[虽然从时间/因果关系的角度来看,与垃圾收集和Finalize
相关的一些行为可能有点奇怪,这些可以被描述为正常的因果关系规则的例外,而不是对它们的完全撤销]。这种情况与C中的情况非常不同,其中许多类型的数据相关错误(例如整数溢出)可能导致编译器以任意方式运行,包括做出必要的假设以避免溢出。在超现代C哲学中鼓励的真正可怕的未定义行为并不存在于C#或其他.NET语言之外"不安全"块。
答案 5 :(得分:0)
总的来说,我会说不。
在自动变量初始化之前使用。
必须初始化所有变量。如果没有异常发生。
除以零
抛出异常。
将数组索引越界
抛出异常
正如Aequitarum Custos指出的那样,你可以使用不安全的代码。那么这不是真正的C#,你明确地选择退出C#环境。
答案 6 :(得分:-1)
并不是真正的维基意义,但我想我脑海中最明显的例子就是编写一些线程代码,但就像任何语言一样。