免责声明:这与Nullable<bool>
或其他内容无关。
我看到有人创建的bool值既不是true
也不是false
。这是为什么在C#中无法进行详尽匹配的一个例子。不幸的是,我丢失了一个示例的源代码,我真的想恢复它。
所以问题是:如何在以下代码中调用default
arm?
bool b = GetMyWeirdBool()
switch (b)
{
case true: Console.WriteLine("true"); break;
case false: Console.WriteLine("false"); break;
default: Console.WriteLine("neither o_0"); break;
}
IIRC通过Marshal
或StructLayout
或其他方式进行了一些肮脏的黑客行为。
答案 0 :(得分:5)
可能是值为43或类似的真实。关键是:Boolean
是谎言 - 它不存在于IL级别。它只是一个整数,其值为零或非零。这适用于&#34; brtrue&#34;并且&#34; brfalse&#34;任何布尔值(1,-1或42)的操作码 - 当你在两个意味着布尔值的值之间进行相等性测试时会出现问题:a&#34; ceq&#34;对于两个实际上不相等的真正的布尔值,操作码将失败。同样,一个&#34;开关&#34;操作码(跳转表 - 在C#中常用于switch
)如果值不是编译器所期望的那样将失败。
这可能会混淆某些API,在相等时将false返回到另一个真值,但在通过brtrue进行比较时报告为true。
通过unsafe
代码将int
视为bool
:
static unsafe bool GetMyWeirdBool()
{
int i = 42;
return *(bool*)(&i);
}
通过IL:
static bool GetMyWeirdBool()
{
var method = new DynamicMethod("evil", typeof(bool), null);
var il = method.GetILGenerator();
il.Emit(OpCodes.Ldc_I4, 42);
il.Emit(OpCodes.Ret);
var func = (Func<bool>)method.CreateDelegate(typeof(Func<bool>));
return func();
}
通过具有重叠字段的struct
:
[StructLayout(LayoutKind.Explicit)]
struct Evil
{
public Evil(int value)
{
Boolean = false;
Int32 = value;
}
[FieldOffset(0)]
public bool Boolean;
[FieldOffset(0)]
public int Int32;
}
static bool GetMyWeirdBool()
{
var val = new Evil(42);
return val.Boolean;
}
答案 1 :(得分:2)
您可以使用具有显式布局的结构:
[StructLayout(LayoutKind.Explicit)]
public struct NotBool
{
[FieldOffset(0)]
public readonly bool Value;
[FieldOffset(0)]
private readonly int Int;
public NotBool(int intValue)
{
Value = false;
Int = intValue;
}
}
测试:
NotBool notBool = new NotBool(255);
switch (notBool.Value)
{
case true:
break;
case false:
break;
default:
Debug.WriteLine("Default");
break;
}
答案 2 :(得分:2)
这似乎对我有用。你得到的都不是。
unsafe
{
for (int i = 0; i < byte.MaxValue; i++)
{
byte val = (byte)i;
bool b = *(bool*)&val;
switch (b)
{
case true: Console.WriteLine("true"); break;
case false: Console.WriteLine("false"); break;
default: Console.WriteLine("neither o_0"); break;
}
}
}
但请注意,这些布尔人在评论时会评估。至少对我来说,0以外的任何东西都是真的。
甚至像这样的比较结果证明是编译器优化。 b == true
b == x
其中x
为真且b
为任何值且未评估为真的protected $casts = [
'column_name' => 'array'
];
。