4
internal static class ChoosingEqOperTest
{
    class A
    {
        public static bool operator ==(A a, A a2) => false;
    }

    class B:A
    {
        public static bool operator ==(B a, B a2) => true;
    }

    static void CheckChosenOper<T>(T x, T x2) where T : A
    {
        Console.WriteLine(x==x2);
    }

    internal static void Do()
    {
        var a  = new A();
        var a2 = new A();
        var b  = new B();
        var b2 = new B();
        CheckChosenOper(a,a2);      // 1. "False"
        CheckChosenOper(b,b2);      // 2. "False" !?
        CheckChosenOper<A>(a,a2);   // 3. "False"
        CheckChosenOper<A>(b, b2);  // 4. "False"
        //CheckChosenOper<B>(a, a2); //Complie Error
        CheckChosenOper<B>(b, b2);  // 5. "False" !?
        Console.WriteLine(a == a2); // 6. "False"
        Console.WriteLine(b == b2); // 7. "True"
        Console.WriteLine(a == b2); // 8. "False"
        Console.WriteLine(b == a2); // 9. "False"
    }
}

一些问题:

A) 为什么#2 & #5 打印“False”?B- 我希望在这些情况下应该从类中获取运算符实现。

B) 我是对的:由于 #8 和 #9 都打印“False” - Cosen 运算符实现是第一个发现的,两种事实参数类型都可以转换为它的参数类型?

c) 选择运算符 == 实现的常见规则是什么?

4

2 回答 2

3

A)好吧,您的方法是一个通用方法,即使您有意指定类型CheckChosenOper,它仍然“使用”类 A 作为基类并且它是自己的运算符。似乎运算符在派生类中没有被覆盖,并且方法只能使用它已知的东西:A类。它不能自行运行并使用反射来搜索其他有效的相等运算符。==<B>CheckChosenOper

B) 不,你错了。在 #8 和 #9 的情况下,编译器有两个选择 - 将 A 向上转换为 B 并将 B1 与 B2 进行比较,将 B 向下转换为 A 并将 A1 与 A2 进行比较。由于向上转换是一个禁忌并且必须通过转换运算符专门完成,因此编译器采用简单的 A1==A2 选择。

C) 好吧,如果我在写一个struct,我肯定会去写一个。以及!=, GetHashCode,IEquatable<>和其他一些东西。但是必须有充分的理由来创建自己的结构,因为它们的行为不同。

于 2020-07-03T11:18:27.423 回答
1
  1. 您在此处使用静态绑定(静态绑定是默认设置,除非您使用dynamic),因此在编译时会发生重载决议。因此,表达式x==x2必须解析为==inA或 in B。它无法解决这两个问题。如果您仔细查看编译器拥有的信息,您会注意到它无法将其解析为 in 中的B那个,因为它只知道那个TisA或其子类。T可能是A或 的兄弟B,在这种情况下调用B重载根本不起作用。您不能将 an 传递AB参数,对吗?

    dynamic您可以通过使用通用方法而不是通用方法来查看预期结果:

     static void CheckChosenOper(dynamic x, dynamic x2)
     {
         Console.WriteLine(x==x2);
     }
    
  2. 编译器必须解析A重载,因为参数之一是A,并且As 不能隐式转换为B,因此不能将其传递给该参数。

  3. 这一切都在语言规范中的一个名为Binary operator overload resolution的部分中进行了描述。但其中大部分遵循与方法解析相同的规则,因此您可能只想阅读它。

于 2020-07-03T11:32:47.813 回答