返回自己类型的方法的接口

我有一个class级的情况

class Foo { Foo Bar() { return new Foo(); } } 

现在我想为它创建一个界面

 class IFoo { ??? Bar(); } 

什么应该代替问号? 每个类都应该返回它自己的类型,而不是Foo。

以下解决方案有效,但看起来并不干净。 我不明白为什么我必须两次指定同一个类,并且当前类型没有类似“this”的东西

这是我以后使用它的方式

 class GenericClass where T : IFoo { T foo = new T(); T item = foo.Bar(); } 

你问:

以下解决方案有效,但看起来并不干净。 我不明白为什么我必须两次指定同一个类,并且当前类型没有类似“this”的东西

你必须指定它两次的原因是因为C#缺少你需要的function。 你想要的是这样的:

 interface IFoo { IFoo Bar(); } class Foo : IFoo { Foo Bar() // should work since Foo is an IFoo, but it's not supported by C# { return new Foo(); } } 

从类型安全的角度来看,这应该工作(它称为返回类型协方差 )。 事实上,其他编程语言(如C ++或Java)支持此function,请参阅Wikipedia上的此示例 。 遗憾的是,C#不支持返回类型协方差 (甚至不是C#4.0,它引入了generics的协方差),这就是为什么你必须使用其他答案中说明的“generics变通方法”。

Covariant返回类型以及“this”类型是新版C#的建议function:

  • 冠军“协变回归类型”
  • 建议:支持“当前对象的类型”作为声明的返回类型。

您可以添加generics类型并使用接口类型约束它:

 public interface IFoo { T Bar(); } 

你可以按如下方式实现:

 public class Foo : IFoo { public Foo Bar() { return new Foo(); } } public class Cheese : IFoo { public Cheese Bar() { return new Cheese(); } } 

更新 ,如果您从不关心Foo的具体返回类型,那么您可以执行以下操作:

 public interface IFoo { IFoo Bar(); } 

实现方式如下:

 public class Foo : IFoo { public IFoo Bar() { return new Foo(); } } 

然后在你的generics类中:

 public class GenericClass where T : class, IFoo, new() { public T Rar() { T foo = new T(); T item = foo.Bar() as T; return item; } } 

GenericClass.Rar(); 将是Foo的具体实现。

我认为真正的问题是:为什么你需要界面中的派生类型? 接口正是出于这个原因 – 从具体类中抽象出来。 如果它只是为了方便,那么在调用Bar()之后你不必强制转换为Foo,你可以显式地实现接口:

 interface IFoo { IFoo Bar(); } class Foo : IFoo { public Foo Bar() { return new Foo(); } IFoo IFoo.Bar() { return Bar(); } } 

问自己一个问题:为什么在需要具体类型时引入界面?

您可以使用抽象基类和显式成员实现来实现此目的。 首先,声明你的界面如下:

 interface IFoo { IFoo Bar(); } 

然后,声明一个以显式方式实现IFoo的通用抽象类,并声明一种抽象方法,即“重载”Bar(),但是以通用方式:

 abstract class BaseFooImpl : IFoo where T : BaseFooImpl { public abstract T Bar(); IFoo IFoo.Bar() { return Bar(); // this will call the abstract Bar() } } 

现在,定义您的具体类,如下所示:

 class ConcreteFoo : BaseFooImpl { public override ConcreteFoo Bar() { return this; // for example, of course. } } 

这种方法的优点是您始终可以使用非genericsIFoo引用来保存具体实例 。 如果你使你的界面通用,你不能,例如,声明这些:

 IFoo mammalInstance, fishInstance; // Instead of IFoo mammalInstance; IFoo fishInstance; List manyInstances; // Instead of List>, which doesn't even work AFAIK 
 public interface IFoo { T Bar(); } 

您的实施将是:

 class Foo : IFoo { Foo Bar() { return new Foo(); } } class Baz : IFoo { Baz Bar() { return new Baz(); } } 

您需要使接口通用,如下所示:

 interface IFoo where TClass : IFoo, class { TClass Bar(); } 

不确定你想要完成什么,但可以这样做:

 interface IFoo { T Bar(); } class Foo:IFoo { #region IFoo Members public Foo Bar() { return new Foo(); } #endregion } 

或者像这样:

  interface IFoo { IFoo Bar(); } class Foo : IFoo { #region IFoo Members public IFoo Bar() { return new Foo(); } #endregion }