编译时泛型语法

3
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 来查看 GenericWrapper 的 T 实现。
我知道我可以通过使用第一种方法或者使用 object 作为参数并进行运行时检查来使其编译通过,但这不是问题的关键;) 我很大程度上怀疑这是我的唯一两个选择。
谢谢

1
请查看以下问题:https://dev59.com/EFXTa4cB1Zd3GeqPxwq1#5243446 - Matías Fidemraizer
它无法工作是由于C#的限制。但是如果您更详细地说明您想要实现什么,可能会有更好的编写方法。;-) - Achim
2个回答

4
我猜答案是否定的,但是我能否让最后一行编译通过呢?
不行。Create有两个泛型类型参数。你要么不指定,要么同时指定。如果没有指定,则编译器将尝试从调用参数中推断类型。然而,在此情况下,它无法推断出类型,因为T1从未出现在参数列表中。因此,你必须同时指定这两个参数。

我相信没有必要再解释更多的原因了。请看我的评论,那是一个关于几乎同样事情的长时间讨论 :) - Matías Fidemraizer

2

这里存在两个问题:

  • You want to infer just one type argument, and specify the other. You can't do that with normal type inference. However, you could make Usage generic, thus specifying one type argument there, and letting the other be inferred using the generic method:

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

    That's something I've often done before, but that just leads to the second problem...

  • The type parameter you want to specify (T1) is constrained by the one you want to infer (T2). The above example can't do that, as Usage<WrapperInstance> doesn't "have" a T2 to validate... and you can't constrain an existing type parameter on a generic method - only ones which are introduced in the method.

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

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 类型参数

嗯,谢谢。这是一种有趣的方法。我希望能够指定T1,然后在不必“知道”T2是什么的情况下提示输入T2的实例(即在T1:X < T >中不必知道T T1扩展了哪个类型)。 - Andrew Bullock
@Andrew:很遗憾,你不能这样做,因为T1在限制T2方面受到约束,而不是相反。 - Jon Skeet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接