具有泛型类类型约束的通用方法

时间:2016-06-10 13:04:20

标签: .net generics c++-cli

我有一个通用接口,它有一个带有另一个泛型类型的方法。 该方法的约束应该只允许从类的泛型类型派生的类型。我尝试了以下代码和其他一些可能性,但迄今为止都没有:

generic <class ObjectType>
public interface class IFoo
{
public:
    generic <class ObjectTypeInherited> where ObjectTypeInherited : ObjectType
    ObjectTypeInherited Test();
};

public ref class Derived : IFoo<System::Object^>
{
public:
generic <class ObjectTypeInherited> where ObjectTypeInherited :     System::Object^
    virtual ObjectTypeInherited Test()
    {
        return ObjectTypeInherited();
    }
};

int main(array<System::String ^> ^args)
{
    auto derived = gcnew Derived();
    auto nullString = derived->Test<System::String^>();
    if (nullString == nullptr)
            System::Console::WriteLine("Got a null string!");
    return 0;
}

我的代码收到以下错误:

error C3766: 'Derived' must provide an implementation for the interface 

方法'ObjectTypeInherited IFoo :: Test(void)'

如果我确实将其更改为:

generic <class ObjectTypeInherited> where ObjectTypeInherited :     System::Object^

我收到了另一个错误:

error C3284: the constraints for generic parameter 'ObjectTypeInherited' of function 'ObjectTypeInherited Derived::Test(void)' must match the constraints for generic parameter 'ObjectTypeInherited' of function 'ObjectTypeInherited IFoo<System::Object ^>::Test(void)'

有谁知道如何正确实现?

编辑: System :: Object ^ System :: String ^ 类仅用作示例。通常我会使用2个自己的ref类,如 MyObject MyDerivedObject:MyObject

1 个答案:

答案 0 :(得分:1)

首先 generic <class ObjectTypeInherited> where ObjectTypeInherited : System::Object^。 应该 generic <class ObjectTypeInherited> where ObjectTypeInherited : System::Object

此处没有 ^ 签名。

然后乐趣开始......

不知何故,C++\CLI编译器不希望理解为了实现IFoo<ObjectType>::Test,类不必是通用的。所以我为这个奇怪的问题创建了一个解决方法。

您可以使用System::Object代替MyObjectType。我只是将MyObjectType用于多功能性。

public ref class MyObjectType
{
};

generic <class ObjectType>
public interface class IFoo
{
public:
    generic <class ObjectTypeInherited> where ObjectTypeInherited : ObjectType
    ObjectTypeInherited Test();
};

//All the magic is here. Somehow the C++\CLI compiler does not wish to
//understand that the DerivedBase class does not have to be generic in order
//to implement the IFoo<ObjectType>::Test. As you can see the Whatever type
//name is never used. Although without it the compiler gives the C3284
//error.
generic <class Whatever>
public ref class DerivedBase : public IFoo<MyObjectType^>
{
public:
    //Why not make use of explicit syntax just because we can.
    generic <class ObjectTypeInherited> where ObjectTypeInherited : MyObjectType
    virtual ObjectTypeInherited Test() = IFoo<MyObjectType^>::Test
    {
        return ObjectTypeInherited();
    }
};

//In order to overcome the fake genericness of DerivedBase I provide
//another successor.
public ref class Derived : public DerivedBase<Object^>
{
};

我对Roslyn编译器或C ++ \ CLI没有任何深入的了解,但在我看来,这似乎是一个错误。

如果我对C#托管代码执行相同的操作,它应该看起来很简单。这就是我要阻止自己的地方。即使没有任何奇怪的编译器行为,托管声明在C#端也比C ++ \ CLI更容易维护。

public class MyObjectType
{
}

public interface IFoo<ObjectType>
{
    ObjectTypeInherited Test<ObjectTypeInherited>() where ObjectTypeInherited : ObjectType;
}

public class Derived : IFoo<MyObjectType>
{
    //Explicit
    ObjectTypeInherited IFoo<MyObjectType>.Test<ObjectTypeInherited>()
    {
        return null;
    }

    //Implicit
    public ObjectTypeInherited Test<ObjectTypeInherited>() where ObjectTypeInherited : MyObjectType
    {
        return null;
    }
}