1

次の基本的なクラス レイアウトを検討してください。

public class Base : IComparable<Base>
{
  public int CompareTo(Base other)
  {
    //Do comparison
  }
}

public class Derived : Base, IComparable<Derived>
{
  public int CompareTo(Derived other)
  {
    //Do comparison
  }  
}

public class BaseComparer : IComparer<Base>
{
  public int Compare(Base x, Base y)
  {
   return x.CompareTo(y);
  }
}

そして、それらを次のように使用します。

List<Base> thingies = new List<Base>
{
  new Base(),
  new Derived(),
  new Derived()
};

thingies.Sort(new BaseComparer());

x パラメーターと y パラメーターの両方が Derived インスタンスである状況では、Comparer が Derived.CompareTo メソッドを呼び出すことを期待していました。

ただし、これは当てはまらず、代わりに Base.CompareTo が呼び出され、なぜなのか疑問に思っています。C# 言語仕様で説明されているように、オーバーロードの解決規則に関する私の基本的な理解では、この動作を差し引くことはできないようです。

誰かが私のためにこれに光を当てることができますか?

4

3 に答える 3

5

Baseはその派生クラスについて何も知らないので、メソッドは1 つBaseしかなく、無条件に呼び出されます。 CompareTo

ポイントは、利用可能な参照の実際のタイプに関する情報がないコンパイル時Baseにオーバーロードの解決が行われることです。のメソッドをオーバーロードするのではなく、オーバーライドする必要があります。Derived

public class Derived : Base
{
  public override int CompareTo(Base other)
  {
    //Do comparison
  }  
}

Base.CompareToさらに、メソッドをマークしvirtualます。

これはもう実装されていないことに注意してIComparable<Derived>ください。これを行うことできますが、目的には関係ありません。

于 2010-08-05T09:01:21.223 に答える
1

過負荷の解決は、ここで起こっていることではありません。2 つの独立したメソッドがあります。完全な名前はIComparable<Base>.CompareToIComparable<Derived>.CompareToです。

BaseComparer呼び出し方を知っているのは だけですIComparable<Base>.CompareTo。については何も知りませんIComparable<Derived>

Baseあなたのアプリケーションでは、 aと aを比較することは理にかなっていますか? つまり、 aが a の前または後にあるDerivedと言えますか?BaseDerived

  • もしそうなら、 only IComparable<Base>、または non-genericIComparableにとどまり、サブクラスの型をチェックする準備をしておく方がよいでしょう
  • そうでない場合は、Base抽象化し、IComparable<T>リーフクラスでのみ実装することを検討する必要があります
于 2010-08-05T09:05:51.170 に答える
1

IComparable<Base>IComparable<Derived>は 2 つの異なるタイプであるため、 の 2 つのメソッドCompareToDerived2 つの異なるスロットにマッピングされます。の呼び出しメソッドCompareToによって呼び出されます。asで示し、それを in でオーバーライドして、(部分的に) 期待される動作を得ることができます。BaseComparerIComparable<Base>CompareTo(Base)BasevirtualDerived

public class Base : IComparable<Base>
{
    public virtual int CompareTo(Base other)
    {
        // do comparison
    }
}

public class Derived : Base, IComparable<Derived>
{
    public int CompareTo(Derived other)
    {
        // do comparison
    }

    public override int CompareTo(Base other)
    {
        if (other is Derived)
            return CompareTo((Derived) other);
        return base.CompareTo(other);
    }
}
于 2010-08-05T09:06:46.427 に答える