6

使用如下代码

public class Task
{
  string Name;
  public static bool operator ==(Task t1, Task t2)
  { return t1.Name = t2.Name && t1.GetType() == t2.GetType(); }
}
public class TaskA : Task
{
   int aThing;
   public static bool operator ==(TaskA t1, TaskA t2)
   { 
      return (Task)t1 == (Task)t2 && t1.GetType() == t2.GetType()
          && t1.aThing == t2.aThing; }
}
public class TaskB : Task  //more of the same

class Stuffin
{
   List<Task> Tasks;

   void CheckIt()
   {
      bool theSame = Tasks[0] == Tasks[1];
   }

我正在尝试确保调用派生运算符 (TaskA.==)。

在这里尝试该技术时出现编译错误。

如果运算符不是静态的,我想我可以让它正常工作,因为我可以覆盖基类的运算符。那可能吗?

一旦我知道了,我将如何比较基本属性(我认为转换为任务类型 [(Task)t1 == (Task)t2] 不起作用)?

4

5 回答 5

10

你不能。运算符没有被覆盖,它们被重载。这意味着要使用的实现完全在编译时决定。

可以做的一件事是在 中覆盖EqualsTask调用它==,然后在 中再次TaskA覆盖它。这也使“基本属性”检查变得容易——只需base.EqualsTaskA.Equals.

于 2010-06-25T21:51:46.897 回答
7

你想要做的事情在 C# 中真的很困难。基本上,您想要的是一个运算符,其行为在运行时根据两个参数的运行时类型确定。这很难;== 操作符是根据两个操作数的编译时类型分派的,.Equals 方法是根据接收者的运行时类型而不是参数编译时类型分派的。

在只支持单虚拟分派的语言中实现双分派的标准方法是访问者模式。你可能会调查那个。

有关此主题的进一步阅读,您可以在此处查看我的文章:

http://blogs.msdn.com/b/ericlippert/archive/2009/04/09/double-your-dispatch-double-your-fun.aspx

于 2010-06-25T21:58:52.840 回答
2

那篇文章是关于 C++ 的。将运算符视为静态函数。你不能超载它。

但是,您可以声明实例虚拟方法,并在您的操作符中调用它。但是注意运算符接受两个参数,并且它们可能具有不同的实际类型,因此您需要决定如何从这两个参数中选择一个参数。

public class Task
{
     public virtual bool MyMethod(Task anotherTask) { return true; }

     public static bool operator==(Task t1, Task t2) 
     {
          return t1 == null ? false : t1.MyMethod(t2);
     } 
}

public class TaskA
{
      public override bool MyMethod(Task anotherTask) { return false; }
}
于 2010-06-25T21:56:03.250 回答
1

如果您可以使 Task 成为抽象类,那么模板方法模式可能是一个很好的遵循。

public abstract class Task
{
    string Name;
    protected abstract bool DoEquals( Task rhs );

    public static bool operator ==(Task t1, Task t2)
    {
        return t1.DoEquals( t2 );
    }
}

public class TaskA : Task
{
    protected bool DoEquals( Task rhs )
    {
        return /* custom compare */
    }
}

public class TaskB : Task
{
    protected bool DoEquals( Task rhs )
    {
        return /* custom compare */
    }
}
于 2010-06-25T22:01:36.717 回答
0

我的混合解决方案似乎有效。

public class Task
{
  string Name;
  public static bool operator ==(Task t1, Task t2)
  { 
    if ((object)t1 == null || (object)t2 == null)
    {
      return (object)t1 == null && (object)t2 == null;
    }

    return t1.Name == t2.Name && t1.GetType() == t2.GetType(); }
  public virtual bool Equals(Task t2)
  {
     return this == t2;
  }
}

public class TaskA : Task
{
  int aThing;
  public static bool operator ==(TaskA t1, TaskA t2)
  { 
    if ((object)t1 == null || (object)t2 == null)
    {
      return (object)t1 == null && (object)t2 == null;
    }

    return (Task)t1 == (Task)t2 && t1.aThing == t2.aThing;
  }
  public override bool Equals(Task t2)
  {
    return this == t2 as TaskA;
  }
}
于 2010-06-29T19:30:35.040 回答