5

如果在 C# 中可以进行以下操作,我只是在徘徊。

假设我有一个类似 List 的界面来强制执行操作reverse。IE:

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 是 another ListImplementation,就像这样:

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

同时仍然实现了足够通用的接口。

如果这令人困惑,请告诉我,我将澄清/添加任何必要的细节或更正。谢谢!

兴趣来源

以下是为什么这对我来说很有趣的解释。

我通过它继承的所有接口(特征)跟踪了 scala 集合中调用的函数(这是一个具体reversed类型List

我的发现非常好奇。

原始reverse方法是在GenSeqLiketrait上抽象定义的。

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


然后,有趣的是接下来的两个特征:

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功能的“免费”版本,但它们都根据各自的“接口”(特征)工作。所以reverseonSeq返回一个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只是另一个一直到 的特征“链” 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 回答