如何在实现接口时从通用方法正确返回T?

时间:2009-06-25 20:25:48

标签: c# generics polymorphism

我正在处理一个错误。在重新创建以下示例的错误时,我能够确定问题发生的原因。但我坚持要求更好的解决方案。所以给出以下程序:

public interface IFoo<T> {
    T OutputType(T param);
}

class Foo : IFoo<Foo> {
    public virtual Foo OutputType(Foo param) {
        Console.WriteLine("foo");
        return param;
    }
}

class Bar : Foo, IFoo<Bar> {
    public virtual Bar OutputType(Bar param) {
        Console.WriteLine("bar");
        return param;    
    }
}

class Program {
    static void Main(string[] args) {
        Bar bar = new Bar();
        CallOutputType(bar);
        bar.OutputType(bar);
    }

    static void CallOutputType<T>(T t) where T : Foo {
        t.OutputType(t);
    }      
}

我期待输出为:

bar
bar

但我得到的是:

foo
bar

看到像这样简化的问题很明显 Bar.OutputType 没有覆盖 Foo.OutputType 。改善这种设计的最佳选择是什么? Bar.OutputType 无法覆盖 Foo.OutputType ,因为签名不同。更改 Bar.OutputType 的签名以匹配 Foo.OutputType 将不起作用,因为不会暗示 IFoo < /强>

5 个答案:

答案 0 :(得分:5)

呃,我对这些东西并不太熟悉,但不应该这样:

static void CallOutputType<T>(T t) where T : IFoo<T>
{
   t.OutputType(t);
}

编译时它起作用了。

答案 1 :(得分:0)

如何将其添加到Bar类:

    public override Foo OutputType(Foo param)
    {
        return this.OutputType((Bar)param);
    }

答案 2 :(得分:0)

如何转换您的界面定义,以便param的类型被声明为扩展IFoo

答案 3 :(得分:0)

我是第二个Spencer - 当你的泛型约束是T:Foo时,它将你的Bar强制转换为Foo,显然你可以调用Foo类的OutputType方法。

答案 4 :(得分:0)

我不确定你最终想要完成的是什么,但这会有所帮助吗?

如果您将Generic添加到实现IFoo的内容中,那么您可以在创建派生对象时指定类型...

public class Foo<TFoo> : IFoo<TFoo>
{

}

//Then you code would allow this...
//Again other then returning Bar both times I am not certain exactly what you are 
//wanting to accomplish But specifying the type at create will allow you to return Bar 
//even if you created a Foo or a Bar...

class Program {
    static void Main(string[] args) {
        Foo foo = new Foo<Bar>();
        CallOutputType(foo);
        foo.OutputType(foo);
    }

    static void CallOutputType<T>(T t) where T : Foo {
        t.OutputType(t);
    }      
}