.net 具有泛型类类型约束的泛型方法

.net 具有泛型类类型约束的泛型方法,.net,generics,c++-cli,.net,Generics,C++ Cli,我有一个泛型接口,它有一个具有另一个泛型类型的方法。 方法的约束应该只允许从类的泛型类型派生的类型。我尝试了以下代码和其他一些可能性,但到目前为止没有成功: generic <class ObjectType> public interface class IFoo { public: generic <class ObjectTypeInherited> where ObjectTypeInherited : ObjectType ObjectTypeI

我有一个泛型接口,它有一个具有另一个泛型类型的方法。 方法的约束应该只允许从类的泛型类型派生的类型。我尝试了以下代码和其他一些可能性,但到目前为止没有成功:

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;
}
方法'ObjectTypeInherited IFoo::Test(void)'

如果我将其更改为:

generic <class ObjectTypeInherited> where ObjectTypeInherited :     System::Object^
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)'
错误C3284:函数“ObjectTypeInherited派生::Test(void)”的泛型参数“ObjectTypeInherited”的约束必须与函数“ObjectTypeInherited IFoo::Test(void)”的泛型参数“ObjectTypeInherited”的约束匹配
有人知道如何正确实施吗

编辑:这里仅以System::Object^和System::String^类为例。通常我会使用两个自己的ref类,比如MyObject和MyDerivedObject:MyObject ObjectTypeInherited:System::Object^中的泛型。 应该是 ObjectTypeInherited:System::Object中的泛型

此处无签名

然后乐趣开始了

不知何故,
C++\CLI
编译器不希望理解类不必是泛型才能实现
IFoo::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^>
{
};
public ref类MyObjectType
{
};
通用的
公共接口类IFoo
{
公众:
ObjectTypeInherited的泛型:ObjectType
ObjectTypeInherited测试();
};
//所有的魔法都在这里。不知何故,C++\CLI编译器不希望
//请理解,DerivedBase类不必是泛型的
//实现IFoo::测试。正如你所看到的,任何类型的
//这个名字从未被使用过。虽然没有它,编译器给出了C3284
//错误。
通用的
public ref类DerivedBase:public IFoo
{
公众:
//为什么不使用显式语法仅仅因为我们可以。
ObjectTypeInherited的泛型:MyObjectType
虚拟ObjectTypeInherited Test()=IFoo::Test
{
返回ObjectTypeInherited();
}
};
//为了克服DerivedBase的伪通用性,我提供了
//另一位继任者。
派生的public ref类:public DerivedBase
{
};
我对Roslyn编译器或C++\CLI都没有深入的了解,但在我看来这似乎是一个bug

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

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;
    }
}
公共类MyObjectType
{
}
公共接口IFoo
{
ObjectTypeInherited Test(),其中ObjectTypeInherited:ObjectType;
}
派生的公共类:IFoo
{
//明确的
ObjectTypeInherited IFoo.Test()
{
返回null;
}
//含蓄的
公共ObjectTypeInherited测试(),其中ObjectTypeInherited:MyObjectType
{
返回null;
}
}

次要更正:
派生的
方法的where子句应该是
where ObjectTypeInherited:System::Object
,没有
^
,但仍然会产生相同的“约束必须匹配”错误。我不确定该错误为什么仍然存在。这对我不起作用,因为我得到以下错误:“ObjectType”的泛型类型参数不能是“System::Object”,它必须是值类型或引用类型的句柄您的#1不正确,这会引发错误C3225“必须是值类型或引用类型的句柄”,正如科斯莫所说。添加了
^
后,您的代码仍然会出现错误C3284,派生::测试的约束必须与IFoo::测试的约束匹配。这可能是VS版本的问题;您正在使用哪个版本的Visual Studio?@DavidYaw感谢您的通知。我用全新的现代Roslyn试过VS2015,但似乎有一个问题。我提出了解决方案,@Zverev-Eugene是的,我也在使用VS2015。在C#的帮助下,我还找到了一个类似的解决方案,在C#的帮助下,它确实更容易实现。我现在刚刚尝试了你的解决方案,我不确定你是如何理解“魔法”的,但它终于起作用了。谢谢!
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;
    }
}