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

And*_*rey 8 c# inheritance interface

我有一个班级的情况

class Foo
{
    Foo Bar()
    {
        return new Foo();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

class IFoo
{
    ??? Bar();
}
Run Code Online (Sandbox Code Playgroud)

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

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

这就是我以后使用它的方式

class GenericClass<T> where T : IFoo
{ 
    T foo = new T();
    T item = foo.Bar();
}
Run Code Online (Sandbox Code Playgroud)

Hei*_*nzi 11

你问:

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

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

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Covariant返回类型以及"this"类型是新版C#的建议功能:


djd*_*d87 8

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

public interface IFoo<T>
{
    T Bar();
}
Run Code Online (Sandbox Code Playgroud)

你可以按如下方式实现:

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

public class Cheese : IFoo<Cheese>
{
    public Cheese Bar()
    {
        return new Cheese();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

public interface IFoo
{
    IFoo Bar();
}
Run Code Online (Sandbox Code Playgroud)

实现如下:

public class Foo : IFoo
{
    public IFoo Bar()
    {
        return new Foo();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在你的泛型类中:

public class GenericClass<T> where T : class, IFoo, new()
{
    public T Rar()
    {
        T foo = new T();
        T item = foo.Bar() as T;
        return item;
    }
}
Run Code Online (Sandbox Code Playgroud)

GenericClass<Foo>.Rar();将是一个具体的实施Foo.