C# 重载的false运算符何时执行,它有什么好处?

C# 重载的false运算符何时执行,它有什么好处?,c#,operator-overloading,C#,Operator Overloading,我一直在搜索实际工作的代码,其中实际执行了重载的false操作符 有些相同,但接受的答案链接到返回404错误的url。我也看了一些其他的问题 我在几乎所有的答案中都发现,false仅在使用短路和类似x&&y时执行。这被评估为T.false(x)?x:T.&(x,y) 好的,我有下面的代码。struct包含一个int,如果int大于零,则认为自己为真: public struct MyStruct { private int _i; public MyStruct(int i)

我一直在搜索实际工作的代码,其中实际执行了重载的
false
操作符

有些相同,但接受的答案链接到返回404错误的url。我也看了一些其他的问题

我在几乎所有的答案中都发现,
false
仅在使用短路和类似
x&&y
时执行。这被评估为
T.false(x)?x:T.&(x,y)

好的,我有下面的代码。
struct
包含一个
int
,如果int大于零,则认为自己为真:

public struct MyStruct {
    private int _i;

    public MyStruct(int i) {
        _i = i;
    }

    public static bool operator true(MyStruct ms) {
        return ms._i > 0;
    }

    public static bool operator false(MyStruct ms) {
        return ms._i <= 0;
    }

    public override string ToString() {
        return this._i.ToString();
    }
}
但是,它甚至不编译。它表示不能将运算符“&&”应用于“MyStruct”和“MyStruct”类型的操作数

我知道我可以实现
&
操作符的重载。那我们就这么做吧。
&
必须返回一个
MyStruct
,因此我不能让它返回一个
bool

public static MyStruct operator &(MyStruct lhs, MyStruct rhs) {
    return new MyStruct(lhs._i & rhs._i);
}
现在代码可以编译了。其输出为
1
-1
。因此,
b1&&b2
的结果与
b2&&b1
的结果不同

如果我调试代码,我会看到
b1&&b2
首先在
b1
上执行
false
操作符,该操作符返回
false
。然后对b1和b2执行
&
运算符,对1和-1执行按位and运算,得到1。因此,它确实是第一次检查b1是否为假

第二个表达式,
b2&&b1
首先执行
b2
上的
false
运算符,该运算符返回
true
。结合我使用短路的事实,它对
b1
没有任何作用,只是打印出
b2
的值

因此,当您使用短路时,将执行
false
运算符。但是,它不会对第二个参数执行
true
false
运算符,而是对操作数执行重载的
&
运算符

这什么时候有用?或者,我如何创建我的类型,以便它可以检查这两个变量是否都为真?

编辑-

通过阅读链接文章,我能够获得以下使用true和false运算符的输出:

op false on 1
op & on 1 -1
op true on 1
op true on -1
FALSE
op false on -1
op true on -1
FALSE
op true on 1
op true on 1
TRUE
op true on -1
op & on -1 1
op true on -1
op true on 1
TRUE
使用代码:

class Program
{
    static void Main(string[] args)
    {
        MyStruct b1 = new MyStruct(1); // to be considered true
        MyStruct b2 = new MyStruct(-1); // to be considered false

        Console.WriteLine((b1 && b2) ? "TRUE" : "FALSE");
        Console.WriteLine((b2 && b1) ? "TRUE" : "FALSE");

        Console.WriteLine((b1 || b2) ? "TRUE" : "FALSE");
        Console.WriteLine((b2 || b1) ? "TRUE" : "FALSE");

        Console.ReadLine();
    }
}

public struct MyStruct
{
    private int _i;

    public MyStruct(int i)
    {
        _i = i;
    }

    public static bool operator true(MyStruct ms)
    {
        Console.WriteLine("op true on {0}", ms);
        return ms._i > 0;
    }

    public static bool operator false(MyStruct ms)
    {
        Console.WriteLine("op false on {0}", ms);
        return ms._i <= 0;
    }

    public static MyStruct operator &(MyStruct lhs, MyStruct rhs)
    {
        Console.WriteLine("op & on {0} {1}", lhs, rhs);

        if (lhs)
        {
            return rhs;
        }
        else
        {
            return new MyStruct(-1); //-1 is false
        }
    }

    public static MyStruct operator |(MyStruct lhs, MyStruct rhs)
    {
        Console.WriteLine("op & on {0} {1}", lhs, rhs);

        if (lhs)
        {
            return lhs;
        }
        else
        {
            return rhs;
        }
    }

    public override string ToString()
    {
        return this._i.ToString();
    }
}
代码:

类程序
{
静态void Main(字符串[]参数)
{
MyStruct b1=新的MyStruct(1);//被认为是真的
MyStruct b2=new MyStruct(-1);//将被视为false
控制台写入线(b1和b2);
控制台写入线(b2和b1);
控制台写入线(b2 | | b1);
控制台写入线(b1 | | b2);
Console.ReadLine();
}
}
公共结构MyStruct
{
私人互联网;;
公共MyStruct(int i)
{
_i=i;
}
公共静态布尔运算符true(MyStruct ms)
{
WriteLine(“op true on{0}”,ms);
返回ms._i>0;
}
公共静态布尔运算符false(MyStruct ms)
{
WriteLine(“在{0}上的op false”,ms);
返回ms._i0;
}
公共重写字符串ToString()
{
将此返回。_i.ToString();
}
}

您提到的404 URL的内容可以在这里找到:

作者所指的文章如下:

为了避免再次出现同样的问题,以下是本文的要点:

几个月前,我发布了关于我们的查询API的文章,并解释了它是如何工作的。我们的查询API允许我们使用强类型C#语法表达查询:

相关的运算符重载如下所示

公共静态布尔运算符true(标准){
返回false;
}
公共静态布尔运算符false(标准){
返回false;
}
公共静态标准运算符&(标准lhs、标准rhs){
返回新的AND标准(左侧、右侧);
}
公共静态标准运算符|(标准lhs、标准rhs){
返回新的OrCriteria(左、右);
}
来自Microsoft(http://msdn.microsoft.com/en-us/library/6292hy1k.aspx):

在C#2.0之前,true和false运算符用于创建用户定义的 与SqlBool等类型兼容的可空值类型。然而, 该语言现在提供了对可空值类型的内置支持,以及 只要有可能,您就应该使用它们,而不是重载true和 假操作员


如果您希望将对象计算为布尔值,请删除运算符true和运算符false重载,然后使用布尔重载。

回答您的最后一个问题:“如何创建我的类型,以便它可以检查这两个变量是否都为真?”-只需使用
&
运算符。
&&
的全部要点是短路,以便在不需要时不检查第二个参数

看看这个:

Console.WriteLine(b1 & b2); // outputs 1
Console.WriteLine(b2 & b1); // outputs 1
实际上,您缺少了一个重要的部分,它允许您将MyStruct(与
&
|
一起)作为布尔值使用—隐式转换为
bool

public static implicit operator bool(MyStruct ms) {
    return ms._i > 0;
}
这允许您使用MyStruct(以及运算符的结果),如下所示:

作为最后一个,可能是最重要的,请注意:您的示例中的问题来自这样一个事实:您希望执行逻辑操作(检查
MyStruct
的两个实例是否为
true
),但您的
运算符为此目的实现得不正确。它以二进制算术的方式工作,当使用参数调用
MyStruct(1)
true
)和
MyStruct(-1)
false
)时,会生成值为
1
MyStruct的实例。所以它基本上是这样做的
(true&false)==true
。这就是为什么在您的示例中,
b1&&b2
给出了与
b2&&b1
不同的结果。基于此运算符的任何其他逻辑
class Program
{
    static void Main(string[] args)
    {
        MyStruct b1 = new MyStruct(1); // to be considered true
        MyStruct b2 = new MyStruct(-1); // to be considered false

        Console.WriteLine(b1 && b2);
        Console.WriteLine(b2 && b1);

        Console.WriteLine(b2 || b1);
        Console.WriteLine(b1 || b2);

        Console.ReadLine();
    }
}

public struct MyStruct
{
    private int _i;

    public MyStruct(int i)
    {
        _i = i;
    }

    public static bool operator true(MyStruct ms)
    {
        Console.WriteLine("op true on {0}", ms);
        return ms._i > 0;
    }

    public static bool operator false(MyStruct ms)
    {
        Console.WriteLine("op false on {0}", ms);
        return ms._i <= 0;
    }

    public static implicit operator bool(MyStruct ms)
    {
        Console.WriteLine("op bool on {0}", ms);
        return ms._i > 0;
    }

    public override string ToString()
    {
        return this._i.ToString();
    }
}
List<Customer> customers = repository.FindAll(Customer.Columns.Age == 20 & Customer.Columns.Name == “foo”);
repository.FindAll(Customer.Columns.Age == 20 && Customer.Columns.Name == “foo”);

repository.FindAll(Customer.Columns.FirstName == “Foo” || Customer.Columns.LastName == “Bar”);
public static bool operator true(Criteria<T> criteria) {
   return false;
}

public static bool operator false(Criteria<T> criteria) {
   return false;
}

public static Criteria<T> operator &(Criteria<T> lhs, Criteria<T> rhs) {
   return new AndCriteria<T>(lhs, rhs);
}

public static Criteria<T> operator |(Criteria<T> lhs, Criteria<T> rhs) {
   return new OrCriteria<T>(lhs, rhs);
}
Console.WriteLine(b1 & b2); // outputs 1
Console.WriteLine(b2 & b1); // outputs 1
public static implicit operator bool(MyStruct ms) {
    return ms._i > 0;
}
if (b1 & b2)
    Console.WriteLine("foo");