代码之家  ›  专栏  ›  技术社区  ›  Carl Hörberg

通用扩展方法中的额外通用参数?

  •  7
  • Carl Hörberg  · 技术社区  · 16 年前

    我想为使用另一个泛型类型(在本例中是tc)的泛型类A创建一个扩展方法,但我想这不可能?

    class Program
    {
        static void Main(string[] args)
        {
            var a = new A<B, B>();
            a.DoIt<B>();
        }
    }
    
    static class Ext
    {
        public static A<TA, TB> DoIt<TA, TB, TC>(this A<TA, TB> a)
        {
            return a;
        }
    }
    
    class A<TA, TB> { }
    class B { }
    
    3 回复  |  直到 16 年前
        1
  •  4
  •   Mark Seemann    16 年前

    如果您可以接受轻微的语法更改,那么它是可能的。

    把它改成:

    var a = new A<B, B>(); 
    a.Do().It<B>(); 
    

    诀窍是do方法是 A<TA, TB> :

    public static Doer<TA, TB> Do<TA, TB>(this A<TA, TB> a)
    {
        return new Doer<TA, TB>(a);
    }
    

    诀窍是这个签名让类型推断从 a 这样您就不必显式地指定它们了。

    doer类提供了您需要的通用方法:

    public class Doer<TA, TB>
    {
        public void It<TC>() { }
    }
    
        2
  •  3
  •   David Morton    16 年前

    不,这是可能的,但是您必须给编译器一些可以接受的上下文,说明什么是“tc”。第三个参数tc在代码中的任何地方都没有使用,因此编译器抱怨说它可能是任何东西。但是,如果向类型为tc的扩展方法中添加一个传入参数,则可以完成编译器可以推断tc的实际类型的情况,然后甚至不必在调用该方法时指示类型:

    class Program
    {
        static void Main(string[] args)
        {
            var a = new A<B, B>();
            string tc = "Hi!";
            a.DoIt(tc);
        }
    }
    
    static class Ext
    {
        public static A<TA, TB> DoIt<TA, TB, TC>(this A<TA, TB> a, TC c)
        {
            return a;
        }
    }
    
    class A<TA, TB> { }
    class B { }
    

    但是你必须给编译器一些上下文。

    也就是说,指定通用参数是一项全无的工作。编译器可以推断每个泛型类型参数的类型,或者不能,您必须告诉它它们都是什么。

        3
  •  1
  •   Tim Robinson    16 年前

    你说得对,这是不可能的。必须指定所有类型参数( TA , TB 和 TC 或者它们都没有(并由编译器的类型推断决定)。

    几种可能性:

    • 转弯 DoIt 到一个实例方法中(尽管我想您已经有意将其作为扩展方法)
    • 向添加另一个参数 多伊特 这多少有点限制 总费用 ,意义类型推理将起作用。

    对于第二个示例,请看 Enumerable.Select :对于源类型和目标类型,它有两个类型参数,但它们都是从传递给 Select .