2016-01-07 5 views
0

Просто создайте консольное приложение CLR в Visual Studio для C++ и скопируйте этот код :Ошибка компиляции C++/CLI .ToString() в универсальном классе для типов перечисления: ошибка C2228: слева от '.ToString' должен быть класс/struct/union

#include "stdafx.h" 

using namespace System; 

generic <typename TEnumMgd> 
where TEnumMgd : value class, System::ValueType, System::IConvertible 
public ref class EnumerationGenericClass 
{ 
public: 
    EnumerationGenericClass(TEnumMgd value) 
    { 
     String^ text = value.ToString(); // Cannot compile 
    } 
}; 

public enum class Test{ Foo, Bar }; 

int main(array<System::String ^> ^args) 
{ 
    auto obj = gcnew EnumerationGenericClass<Test>(Test::Foo); 
    return 0; 
} 

Это терпит неудачу с «ошибка C2228: слева от„.ToString“должен иметь класс/структуры/объединения», но почему и как это можно решить? Предпочтительно без бокса.

UPDATE: Изменен формат для разделения вопросов и ответов.

+0

value-> ToString() - это правильный синтаксис, который вы хотите вызвать методом, реализованным System :: Object, ссылочным типом. Вы получаете Opcodes.Constrained вместо Opcodes.Box в MSIL, как хотите. Посмотрите на это с помощью ildasm.exe –

+0

Я предполагаю, что это потому, что это был единственный общий способ сделать этот родовой код на C++. В C# это не проблема, потому что аксессор всегда «.». В C++ ацессор либо «.» или "->" в зависимости от этого значения или типа ref. Для общего типа тип может быть таким, поэтому я предполагаю, что им нужно было выбрать и, таким образом, выбрать «->» по умолчанию. – nietras

+0

@HansPassant хорошо Я не хочу вызывать ToString() на объекте, но тип значения эквивалентен, но это то, что происходит в IL, так что это нормально. Спасибо за ваш ответ. – nietras

ответ

0

Это может скомпилировать, если вы вместо того, чтобы написать:

 String^ text = value->ToString(); 

То есть, C++/CLI не использует "->" аксессор для общих типов независимо от того, что. Однако IL, который выводится для ctor, показан ниже, поэтому он не помещается в коробку, а ограничивается типом значений, как ожидалось.

.method public hidebysig specialname rtspecialname 
     instance void .ctor(!TEnumMgd 'value') cil managed 
{ 
    // Code size  29 (0x1d) 
    .maxstack 1 
    .locals ([0] string text) 
    IL_0000: ldnull 
    IL_0001: stloc.0 
    IL_0002: ldarg.0 
    IL_0003: call  instance void [mscorlib]System.Object::.ctor() 
    IL_0008: ldarga.s 'value' 
    IL_000a: constrained. !TEnumMgd 
    IL_0010: callvirt instance string [mscorlib]System.ValueType::ToString() 
    IL_0015: stloc.0 
    IL_0016: ldloc.0 
    IL_0017: call  void [mscorlib]System.Console::WriteLine(string) 
    IL_001c: ret 
} // end of method EnumerationGenericClass`1::.ctor