代码之家  ›  专栏  ›  技术社区  ›  Bob

如何在实现接口时正确地从泛型方法返回t?

  •  2
  • Bob  · 技术社区  · 16 年前

    我正在处理一个错误。在为下面的示例重新创建bug时,我能够确定问题发生的原因。但我一直在寻求更好的解决方案。因此,考虑到以下程序:

    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
    

    看到这样简化的问题,很明显 输出类型 不是压倒性的 输出输出类型 . 我改进这个设计的最佳选择是什么? 输出类型 不能超越 输出输出类型 因为签名是不同的。更改的签名 输出类型 相配 输出输出类型 那就不行了 酒吧 不会是简单的 IFOO .

    5 回复  |  直到 16 年前
        1
  •  5
  •   Spencer Ruport    16 年前

    呃,我不太熟悉这些东西,但不应该是:

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

    我编译它时它起作用了。

        2
  •  0
  •   BFree    16 年前

    把这个添加到bar类中怎么样:

        public override Foo OutputType(Foo param)
        {
            return this.OutputType((Bar)param);
        }
    
        3
  •  0
  •   Edward Q. Bridges    16 年前

    如何转换接口定义以便 param 的类型声明为扩展 IFoo ?

        4
  •  0
  •   Steffen    16 年前

    第二个是Spencer,当你的泛型约束是t:foo时,它将你的条类型化为foo,显然你可以调用foo类的outputtype方法。

        5
  •  0
  •   bytebender    16 年前

    我不确定你到底想做什么,但这会有帮助吗?

    如果将泛型添加到实现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);
        }      
    }