mal*_*rdz 20 c# boolean pex bitwise-operators logical-operators
我正在学习C#并且一直在搞乱Pex for fun网站.该站点向您提出重新实施秘密算法的挑战,方法是在站点中键入代码并检查输入和输出在您的实现和秘密实现之间的差异.
无论如何,我被困在一个名为XAndY的基本代码决斗上.
从名称来看,答案显而易见:
public static bool Puzzle(bool x, bool y)
{
return x && y;
}
Run Code Online (Sandbox Code Playgroud)
但是,这是不正确的,Pex告诉我,以下输入产生的结果与秘密实现不同:
输入:
x:true y:true(0x02)
输出:
我的实现:true(0x02)
秘密实施:假
不匹配你的拼图方法产生了错误的结果.
代码:Puzzle(true,PexSafeHelpers.ByteToBoolean((byte)2));
在尝试比较不同类型的true之后出现了很多困惑之后,我意识到Pex正在寻找的实现实际上只是使用了按位AND:
return x & y;
Run Code Online (Sandbox Code Playgroud)
我认为,出于语义和短路的原因,您应该使用逻辑&&
来比较布尔值,但无论如何:
x & y
并且对于所有可能的bool参数x && y
最终没有相同的输出?(或者它可能是Pex中的一些东西吗?)true
C#中不同的bool值?如果是这样,怎么样?Mic*_*Liu 20
这个难题正在利用我认为是C#编译器中的错误.(该bug也会影响VB.NET.)
在C#5.0规范中,§4.1.8说"类型的可能值bool
是true
和false
",而§7.11.3说这operator &(bool x, bool y)
是一个逻辑运算符:
结果
x & y
是true
,如果这两个x
和y
的true
.否则,结果是false
.
这显然违反了true & true
收益规范false
.这是怎么回事?
在运行时,a bool
由1字节整数表示.C#编译器使用0表示false
,1表示true
.为了实现&
运算符,C#编译器在生成的IL中发出按位 AND
指令.乍一看,这似乎没问题:AND
涉及0和1的按位运算完全对应于AND
涉及false
和的逻辑运算true
.
但是,CLI规范的 §III.1.1.2 明确允许用bool
0或1以外的整数表示:
CLI布尔类型在内存中占用1个字节.全零的位模式表示值false.设置任何一个或多个位的位模式(类似于非零整数)表示值true.
超越C#的范围,确实可能 - 并且完全合法 - 创建一个bool
值,例如2,从而导致&
意外行为.这就是Pex网站正在做的事情.
这是一个演示:
using System;
using System.Reflection.Emit;
class Program
{
static void Main()
{
DynamicMethod method =
new DynamicMethod("ByteToBoolean", typeof(bool), new[] { typeof(byte) });
ILGenerator il = method.GetILGenerator();
il.Emit(OpCodes.Ldarg_0); // Load the byte argument...
il.Emit(OpCodes.Ret); // and "cast" it directly to bool.
var byteToBoolean =
(Func<byte, bool>)method.CreateDelegate(typeof(Func<byte, bool>));
bool x = true;
bool y = byteToBoolean(2);
Console.WriteLine(x); // True
Console.WriteLine(y); // True
Console.WriteLine(x && y); // True
Console.WriteLine(x & y); // False (!) because 1 & 2 == 0
Console.WriteLine(y.Equals(false)); // False
Console.WriteLine(y.Equals(true)); // False (!) because 2 != 1
}
}
Run Code Online (Sandbox Code Playgroud)
所以你的问题的答案是:
x & y
,并x && y
有不同的值.但是,此行为违反了C#规范.Boolean.Equals
(如上所示)区true
分值.但是,此行为违反了CLI规范Boolean.Equals
. 归档时间: |
|
查看次数: |
2867 次 |
最近记录: |