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

できません。演算子はオーバーライドされず、オーバーロードされます。つまり、使用する実装はコンパイル時に完全に決定されます。

できることの 1 つは、 でオーバーライドEqualsTaskて から呼び出し、 で再度==オーバーライドすることです。これにより、「基本プロパティ」のチェックも簡単になります - から呼び出すだけです。TaskAbase.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++ に関するものでした。演算子を静的関数と見なします。過負荷にすることはできません。

ただし、インスタンス仮想メソッドを宣言して、オペレーター内で呼び出すことができます。ただし、演​​算子は 2 つの引数を受け入れ、実際の型が異なる場合があることに注意してください。そのため、これら 2 つの引数から 1 つの引数を優先する方法を決定する必要があります。

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

My hybrid solution that seems to work.

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 に答える