Why does implementing IBitwiseOperators not allow short-circuiting operators?

In the process of investigating a .NET API proposal, to add the new System.Numerics interfaces to System.Boolean, it transpired that && and || short-circuiting operators need the operators true and false to be implemented.

I tried to test doing so with an interface containing the static abstract operators (a new feature for .NET 7):

public interface ITruthOperators<TSelf>
    where TSelf : ITruthOperators<TSelf>?
{
    static abstract bool operator true(TSelf left);

    static abstract bool operator false(TSelf left);
            
    static abstract TSelf TruthyIdentity { get; }
            
    static abstract TSelf FalseyIdentity { get; }
}

And a custom boolean type:

public struct MyBool(bool val) : ITruthOperators<MyBool>, IBitwiseOperators<MyBool, MyBool, MyBool>
{
    public bool Value {get;} = val;
    
    public static bool operator true(MyBool b) => b.Value;
    
    public static bool operator false(MyBool b) => b.Value;
    
    public static MyBool TruthyIdentity => new(true);
    
    public static MyBool FalseyIdentity => new(false);
    
    public static MyBool operator &(MyBool a, MyBool b) => new(a.Value & b.Value);
    
    public static MyBool operator |(MyBool a, MyBool b) => new(a.Value | b.Value);
    
    public static MyBool operator ^(MyBool a, MyBool b) => new(a.Value ^ b.Value);
    
    public static MyBool operator ~(MyBool val) => new(!val.Value);
}

You can now write something like if (T.TruthyIdentity) or if (!someMyBool). You can also use non-short-circuiting operators someMyBool & someOtherMyBool

But using short-circuiting operators still does not work.

public T IsTrue<T>(T a, T b) where T : ITruthOperators<T>, IBitwiseOperators<T>
{
    return a && b;
}

just gets you:

In order to be applicable as a short circuit operator a user-defined logical operator ('IBitwiseOperators<T, T, T>.operator &(T, T)') must have the same return type and parameter types

This makes no sense, because the operator & defined on IBitwiseOperators<TSelf,TOther,TResult> is defined as

public static abstract TResult operator & (TSelf left, TOther right);

so if you re-ify the generic type as IBitwiseOperators<MyBool, MyBool, MyBool> then you get:

public static abstract MyBool operator & (MyBool left, MyBool right);

I tried to redefine my own IBitwiseOperators<TSelf> where all the parameters and return types are the same generic parameter, in case that was the issue.

public interface IBitwiseOperators<TSelf>
    where TSelf : IBitwiseOperators<TSelf>?
{
    static abstract TSelf operator &(TSelf left, TSelf right);

    static abstract TSelf operator |(TSelf left, TSelf right);

    static abstract TSelf operator ^(TSelf left, TSelf right);

    static abstract TSelf operator ~(TSelf value);
}

This got a different error:

In order for 'IBitwiseOperators<T>.operator &(T, T)' to be applicable as a short circuit operator, its declaring type 'IBitwiseOperators<T>' must define operator true and operator false

Which again makes no sense, because T in the function is constrained to both IBitwiseOperators and ITruthOperators.

The only way I could get this to work was if I placed all the operators in the same interface.See this fiddle for that attempt which finally worked.


Note the definition for short-circuiting operators in the C# Spec:

When the operands of && or || are of types that declare an applicable user-defined operator & or operator |, both of the following shall be true, where T is the type in which the selected operator is declared:

  • The return type and the type of each parameter of the selected operator shall be T. In other words, the operator shall compute the logical AND or the logical OR of two operands of type T, and shall return a result of type T.
  • T shall contain declarations of operator true and operator false.

A binding-time error occurs if either of these requirements is not satisfied. Otherwise, the && or || operation is evaluated by combining the user-defined operator true or operator false with the selected user-defined operator:

etc…

What do the words “where T is the type in which the selected operator is declared” mean here? Does that mean the interface, or does it mean the generic type? I think it should mean the generic type. Remember we are dealing with a generic type that is constrained to those interfaces, the variables we are handling are actually of type T.

So what I’m essentially asking is: is this a bug in the compiler, or is this by design?

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật