编译时间泛型语法

时间:2011-04-13 13:37:49

标签: c# generics

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以查看它实现的T GenericWrapper

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

由于

2 个答案:

答案 0 :(得分:4)

  

我怀疑答案是否定的,但有没有办法让最后一行编译?

没有。 Create有两个通用类型参数。您可以指定none,也可以同时指定两者。如果为none,编译器将尝试从调用参数中推断出类型。但是,在这种情况下它不能,因为T1永远不会出现在参数列表中。因此,您必须同时指定。

答案 1 :(得分:2)

这里有两个问题:

  • 您只想推断一个类型参数,并指定另一个。你不能用普通的类型推断做到这一点。但是,可以使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类型参数