编译时泛型语法


class GenericWrapper<T>
{   
}
class WrapperInstance : GenericWrapper<string>
{   
}
class Usage
{
    public static Usage Create<T1, T2> (T2 t2) where T1 : GenericWrapper<T2>
    {
        return null;
    }
}
...
// works
Usage.Create<WrapperInstance, string>("bar");
// doesnt work
Usage.Create<WrapperInstance>("bar");

我怀疑答案是否定的,但是有一种方法可以使最后一行编译吗?

我希望编译器强迫我提供一个字符串参数,而不必知道或先去检查WrapperInstance,看看GenericWrapperT实现了什么。

我知道我可以通过使用第一种方法或通过将object作为参数并进行运行时检查来编译,但这不是问题;)我很怀疑这是我仅有的两个选择。

谢谢

我怀疑答案是否定的,但是有一种方法可以使最后一行编译吗?

Create有两个泛型类型参数。要么不指定,要么两者都指定。如果没有,编译器将尝试从调用参数推断类型。然而,在这种情况下,它不能,因为T1从未出现在参数列表中。

这里有两个问题:

  • 您只想推断一个类型参数,并指定另一个。普通的类型推断不能这样做。但是,可以使Usage泛型,从而在那里指定一个类型参数,并使用泛型方法来推断另一个:

    Usage<WrapperInstance>.Create("foo");
    

    这是我以前经常做的事情,但这只会导致第二个问题…

  • 你想要指定的类型参数(T1)受到你想要推断的类型参数(T2)的约束。上面的例子不能这样做,因为Usage<WrapperInstance>没有"有"T2来验证…而且你不能在泛型方法上约束现有的类型参数——只能约束方法中引入的类型参数。

我认为有一种方法可以做到这一点:

public class Usage
{
    public static Usage<T2> For<T2>(T2 t2)
    {
        return new Usage<T2>(t2);
    }
}
public class Usage<T2>
{
    private readonly T2 t2; // Assuming we need it
    public Usage(T2 t2)
    {
        this.t2 = t2;
    }
    // I don't know what return type you really want here
    public static Foo Create<T1>() where T1 : GenericWrapper<T2>
    {
        // Whatever
    }
}

你可以这样使用:

Usage.Foo("bar").Create<WrapperInstance>();

如果不知道你想要做什么,我不知道这是否有帮助-但是确实设法完成了你想要的:

  • 验证WrapperInstance类型参数
  • 推断string类型参数

最新更新