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

时间:2010-02-26 22:00:26

标签: c# generics type-inference

我想为泛型类A创建一个扩展方法,它采用另一个泛型类型(在本例中为TC),但我想这可能吗?

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 个答案:

答案 0 :(得分:4)

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

将其更改为:

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获取TA和TB,这样您就不必明确指定它们。

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

public class Doer<TA, TB>
{
    public void It<TC>() { }
}

答案 1 :(得分:3)

不,这是可能的,但你必须给编译器一些可接受的“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 { }

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

话虽如此,指定通用参数是一种全有或全无的努力。编译器可以推断出每个泛型类型参数的类型,或者它不能,并且你必须告诉它所有类型参数是什么。

答案 2 :(得分:1)

你是对的,这是不可能的。您必须指定所有类型参数(TATBTC),或者不指定任何类型参数(并将其留给编译器的类型推断)。

有几种可能性:

  • DoIt转换为实例方法(虽然我猜您已故意将其作为扩展方法)
  • DoIt添加另一个参数,以某种方式约束TC,这意味着类型推断将起作用

有关第二个示例,请查看Enumerable.Select:它有两个类型参数,对于源类型和目标类型,但它们都是从传递给Select的参数推断出来的。 / p>