如何为 bool 创建 1 / 0 返回类型?

How to create 1 / 0 returning type for bool?

在 C# 中,如何为 bool 创建自定义 type/cast?为了更好地解释,我想要这样的表达式:

bool cond=...;
int myVar=  cond as customType;

所以,我希望 customType 表现为 myVar 变为 01,具体取决于 cond(如果为真,则为 1,否则 0).

这可能吗?


请不要向我提供 cond ? 1 : 0 解决方案或其他解决方案。我问的正是我问的,所以在标记之前重新阅读(或分析)它。

如果您需要布尔值(1 或 0),您应该使用 GetHashCode 函数 Boolea.GetHashCode

我在这里举了一个例子

bool v1 = true;
bool v2 = false;
int res;

Console.WriteLine($"v1: {v1.GetHashCode()}, v2: {v2.GetHashCode()}");

是的,你可以这样做。如果你想要一个行为类似于内置类型的自定义类型,你必须注意重写一些从 System.Object 继承的方法。此外,您还需要转换运算符。

让我们创建一个名为 Logical 的结构,它具有 int 属性 Value.

public readonly struct Logical : IEquatable<Logical>
{
    public Logical(int value)
    {
        Value = value == 0 ? 0 : 1;
    }

    public Logical(bool cond)
    {
        Value = cond ? 1 : 0;
    }

    public int Value { get; }

    ... conversions and overrides
}

它有 2 个构造函数,允许您从 intbool 构建值。

我们可以声明隐式转换以在 boolLogicalintLogical 以及 Logicalbool 之间进行转换。

public static implicit operator Logical(bool cond) => new Logical(cond);

public static implicit operator Logical(int i) => new Logical(i);

public static implicit operator bool(Logical logical) => logical.Value != 0;

覆盖 EqualsGetHashCode 也很好,以便能够轻松比较值或将它们添加到字典或哈希集中。

public bool Equals(Logical other) // Implements IEquatable<Logical>
{
    return Value.Equals(other.Value);
}

public override bool Equals(object obj)
{
    if (obj is Logical logical) {
        return Equals(logical);
    }
    return base.Equals(obj);
}

public override int GetHashCode() => Value.GetHashCode();

如果重写Equals,自然重载==!=

public static bool operator ==(Logical a, Logical b) => a.Value == b.Value;
public static bool operator !=(Logical a, Logical b) => a.Value != b.Value;

最后,我们覆盖 ToString 以便能够打印 Logicals。

public override string ToString() => Value == 0 ? "FALSE" : "TRUE";

现在,我们可以做这些事情:

double x = 3.14;
Logical logical = x > 0.0;
bool b = logical;

Console.WriteLine($"logical = {logical}");
Console.WriteLine($"b       = {b}");

logical = -3;
Console.WriteLine($"logical = {logical}");
Console.WriteLine($"logical.Value = {logical.Value}");
logical = 0;
Console.WriteLine($"logical = {logical}");
Console.ReadKey();

它打印:

logical = TRUE
b       = True
logical = TRUE
logical.Value = 1
logical = FALSE

您可以做更多的事情。例如,System.Bool 实现了 IComparableIComparable<bool>IConvertibleIEquatable<bool>。它还具有静态 ParseTryParse 方法。您还可以重载其他运算符。参见:Overloadable operators (Operator overloading, C# reference).

答案 here 可能是您应该使用的答案,除非您有充分的理由不这样做。

但是,仅仅因为它很有趣,您也可以使用以下结构的某个版本,这样转换是隐式的,并且您可以同时使用 bool 值和 int 值,而无需任何额外的内存使用:

[StructLayout(LayoutKind.Explicit)]
public struct BoolToInt
{
    [FieldOffset(0)]
    public readonly bool booleanValue;

    [FieldOffset(0)]
    public readonly int integerValue;

    public BoolToInt(bool booleanValue)
    {
        this.integerValue = 0; //irrelevant, will be overwritten, but the compiler can't figure this out
        this.booleanValue = booleanValue;
    }
}

如果您希望能够更改布尔值,可以将其设置为可变的,但这确实违背了结构使用的一般原则。
我强烈建议不要使 integerValue 字段可变。