代码之家  ›  专栏  ›  技术社区  ›  Konamiman

如何将泛型类型指定为泛型方法中的限制

  •  2
  • Konamiman  · 技术社区  · 15 年前

    我有一个这样的类:

    class MyGenericClass<T> { }
    

    另一方面,我有一个聚合器类,用于获取 MyGenericClass 以及派生类,其中每个实例都由具体的类类型和参数类型标识。也就是说, MyGenericClass<int> 不同于 MyGenericClass<string> MyDerivedGenericClass<int> ;每个实例都有一个实例。

    聚合器的主要成员是 GetInstanceOf 方法,它将返回指定类型的单例实例。问题是我想将类型指定为泛型参数,但找不到创建类型限制的方法 “参数的类型必须是MyGenericClass(或派生的)且具有任何参数类型” . 简而言之,我想要这样的东西:

    T GetInstanceOf<T>() where T : MyGenericClass<> //This does not compile
    

    那么,我能做什么?有没有办法规定这种限制?

    编辑: 这个 GetInstanceOf<T> 方法确实返回t,而不是void。

    5 回复  |  直到 15 年前
        1
  •  6
  •   AaronSieb    15 年前

    您可能想要创建一个接口,并让您的泛型类实现它。.NET编译器认为MyGenericClass<int>和MyGenericClass<string>是完全不同的类。

    这将允许您执行如下操作:

    void GetInstanceOf<T>() where T : IMyGenericClass
    

    您还可以使用共享的基类:

    void GetInstanceOf<T>() where T : MyGenericClassBase
    

    最后,您可以尝试向方法中添加第二个类型参数:

    void GetInstanceOf<T, U>() where T: MyGenericClassBase<U>
    

    (我不确定最后一个……我没有现成的编译器来检查它)

    见: http://msdn.microsoft.com/en-us/library/aa479859.aspx#fundamentals_topic12

        2
  •  4
  •   LukeH    15 年前
    interface IMyGenericBase { /* ... */ }
    
    class MyGenericClass<T> : IMyGenericBase { /* ... */ }
    
    class MyDerivedGenericClass<T> : MyGenericClass<T> { /* ... */ }
    
    T GetInstanceOf<T>() where T : IMyGenericBase { /* ... */ }
    
        3
  •  2
  •   Eric Lippert    15 年前

    我认为你让事情变得比需要的复杂得多。退一步来解决实际问题,而不是试图解决一些完全不必要的涉及约束的问题。这看起来非常简单:

    MyGenericClass<T> GetInstanceOfMyGenericClass<T>() 
    { 
        return MyGenericClass<T>.GetSingleton(); 
    }
    

    你想要一个 MyGenericClass<int> 你说 GetInstanceOfMyGenericClass<int>() 完成了。如果你不需要的话,为什么还要纠结于约束呢?

        4
  •  1
  •   Jesse Taber    15 年前

    如果是我,我可能会创建一个接口,让“MyGenericClass”实现该接口,然后在方法签名的“Where”中使用该接口。

        5
  •  1
  •   Reed Copsey    15 年前

    我同意这里的大多数帖子——提供一个界面通常是最好的方法。

    然而,如果 MyGenericClass<T> 恰好是在您的控制之外定义的类,另一个选项是:

     void GetInstanceOf<T, U>() where T : MyGenericClass<U>
    

    不幸的是,这要求调用者也提供MyGenericClass的泛型类型,但是如果不能更改“MyGenericClass”,它将正确编译和运行。