(重新)使用约束类型的通用参数而不声明它们

时间:2010-10-01 11:21:02

标签: c# generics

这可能是不可能的,但我想检查这样的事情是否可以用一种简单的方式表达:

// obviously doesn't work
class Foo<T> : IFoo<T1,T2>
    where T: Bar<T1,T2>
{
    // ...
    Baz<T1,T2> getBaz(){...}
}

现在我声明Foo<T1,T2>,但我不喜欢它在语义上,获得约束的唯一方法是在Bar的通用参数列表中列出Foo我希望减少冗余,而不是添加它。

编辑:Baz<T1,T2>应该是返回类型,而不是方法名称

3 个答案:

答案 0 :(得分:4)

问题在于,它没有定义T1和T2是什么。

你可以这样做:

class Foo<T> : IFoo<int,string>
    where T: Bar<int,string>
{
    // ...
    void Baz(){...}
    // can call e.g. Qux<int, string>();
}

你可以这样做:

class Foo<T, T1, T2> : IFoo<T1,T2>
    where T: Bar<T1,T2>
{
    // ...
    void Baz(){...}
    // can call e.g. Qux<T1, T2>();
}

但实际上,没有办法知道T1和T2是什么(人类甚至无法猜测你正在尝试做什么,所以编译器无法推断它。)

答案 1 :(得分:1)

为给定泛型创建运行时类型所需的类型参数必须在尖括号中使用泛型的类名声明:

class Foo<T, T1, T2> : IFoo<T1, T2> 
          where T: Bar<T1, T2>
{
   //...
   void Baz() {...}
}

基本上,由于Foo<x,y,z>对于x,y和z的任何给定组合都是唯一的,因此它们必须全部声明为“up top”。

请注意,您不需要使用Baz声明'T1,T2',但是 - 已经为类定义了这些类型参数。您可以在ECMA spec for generics

中找到更多信息

答案 2 :(得分:1)

您可以围绕它创建一个包装类,但我怀疑这比原始解决方案更好:

  public class FooWrapper<T1, T2>
  {
     public Foo<Bar<T1, T2>> FooObj;

     public FooWrapper()
     {
        FooObj = new Foo<Bar<T1, T2>>();
     }

     public class Foo<T> : IFoo<T1, T2> where T : Bar<T1, T2>
     {
        // ...
        public void Baz() 
        {
           Type t1 = typeof(T1);
           Type t2 = typeof(T2);
        }
     }
  }