5

C#で次のことが可能かどうか、私はたださまよっています。

operation を義務付ける List のようなインターフェースがあるとしましょうreverse。すなわち:

public interface ReversableList<T> {
      // Return a copy of this list but reversed
      ReversableList<T> Reverse();

      // We still need to return the contained type sometimes
      T Get(int index)
}

ただし、そのインターフェイスを実装すると、次のようになります。

public class ListImplementation<T> : ReversableList<T> 
      ReversableList<T> Reverse();   
}

私はまだインターフェイスを使用することを余儀なくされていますReversableList。したがって、ユーザーが my を直接インスタンス化したとしても、メソッドを呼び出すときListImplementationに対処する必要があります。ReversableListReverse

var concreteList = new ListImplementation<String>();
ReversableList<T> reversed = concreteList.Reverse(); 

一方、私が念頭に置いていたReverse()のは、ListImplementationwill be anotherのことでしたListImplementation

var concreteList = new ListImplementation<String>();
ListImplementation<String> reversed = concreteList.Reverse();

まだ十分に一般的なインターフェースを実装しています。

これが紛らわしい場合はお知らせください。必要な詳細や修正を明確化/追加します。ありがとうございました!

関心の源

以下は、これが私にとって興味深い理由の説明です。

(具体的な型である) scala のコレクションで呼び出さreversedれた関数を、それが継承するすべてのインターフェイス (特性) を介して追跡しました。List

私が見つけたものは非常に興味深いものです。

元のメソッドは、 traitreverseで抽象的に定義されています。GenSeqLike

trait GenSeqLike[+A, +Repr] ...
    def reverse: Repr   // <--- NO BODY, means abstract


次に、 traitを拡張するtrait SeqLikeで具体的に定義します。GenSeqLike

trait SeqLike[+A, +Repr] extends GenSeqLike[A, Repr]
    def reverse: Repr
        //iterates through this seqence
        // and reverses 
        for (x <- this)
           //...etc


次に興味深いのは、次の 2 つの特性です。

trait Seq[+A] extends SeqLike[A, Seq[A]]   //<-- NOTE here is the type for "Repr"
     //no mention of reverse

trait LinearSeq[+A] extends Seq[A] with SeqLike[A, Seq[A]] //<-- NOTE type again
    // no mention of reverse

どちらも関数の「無料」バージョンを取得しreverseますが、どちらもそれぞれの「インターフェース」(特性) に関して機能します。reverseを返しSeqますSeq

最後に、List具象クラスがLinearSeqトレイトを実装し、reverseメソッドを再定義します (効率化のためだと思います)。

sealed abstract class List[+A] extends LinearSeq[A]
                                 with LinearSeqOptimized[A, List[A]] 

      override def reverse: List[A] = {
          //faster impl without foreach iteration
          ...
      }

ここで、LinearSeqOptimizedは単に まで続く特性のもう 1 つの「チェーン」ですSeqLike[A, Repr]

したがって、一般的な「インターフェース」を使用して「動作」を指定する方法、中間の「インターフェース」が何らかの「デフォルト」実装を提供する方法、およびすべてのサブ「インターフェース」とサブタイプがすべて利益を得る方法を見ることができます。戻り値の型を「独自の」型に保ちながら、その実装の。ふぅ。紛らわしいですね!

4

3 に答える 3

4

少しトリッキーかもしれませんが、この方法で行うことができます。

インターフェイスを次のように変更しReversableListます。

public interface ReversableList<L, T> where L : ReversableList<L, T>
{
    // Return a copy of this list but reversed
    L Reverse();
}

次のように実装します。

public class ListImplementation<T> : ReversableList<ListImplementation<T>, T>
{
    public ListImplementation<T> Reverse() { /* code */ }
}
于 2012-09-28T04:46:06.667 に答える
1

のようなものはどうですか

public interface IReversableList<T> where T : IReversableList<T>
{
    // Return a copy of this list but reversed 
    T Reverse();
}

public class ListImplementation<T> : IReversableList<ListImplementation<T>>
{
    public ListImplementation<T> Reverse()
    {
        return new ListImplementation<T>();
    }
}

これは次のように使用できます

var concreteList = new ListImplementation<string>();
ListImplementation<string> reversed = concreteList.Reverse();

編集

インターフェイスに制約を追加しました。

于 2012-09-28T04:58:35.957 に答える
0

この特定のケースは、Enumerable 拡張機能によって既に処理されています: Enumerable.Reverse

 var list = new List<string>(){"a","b","c"};
 list.Reverse();

この質問への回答ではありませんが、将来の検索に役立つかもしれません!

于 2012-09-28T15:47:23.003 に答える