c++/cli ссылка на свойство

Ну, я еще не нашел что-то, что говорит о том, что это невозможно, хотя я начинаю думать, что это возможно. Можете ли вы сделать эту работу?

using namespace System;

template <typename T> 
void unset(Nullable<T>& var) { var = Nullable<T>(); }
void unset(String^% var) { var=nullptr; }

//this is really a C# class in my situation, so I can't change its types
public ref class Foo 
{
public:
   property Nullable<Decimal> Dec;
   property Nullable<int> Num;
   property String^ Str;
};

int main()
{
   Foo^ foo = gcnew Foo;
   foo->Dec = Decimal(1.2);
   foo->Num = 3;
   foo->Str = "hi";

   unset(foo->Dec);
   unset(foo->Num);
   unset(foo->Str);

   Console::WriteLine(foo->Dec);
   Console::WriteLine(foo->Num);
   Console::WriteLine(foo->Str);
}

Обновление: unset вызывается из макроса, генерирующего код, который вызывается примерно для 50 параметров. Я бы предпочел не создавать разновидности макроса для каждого типа.


person Thomas    schedule 31.03.2011    source источник


Ответы (2)


Это невозможно. Установка свойства требует вызова функции установки свойства. Для вызываемого метода невозможно догадаться, что ему нужно вызвать функцию, а не присвоить переданный указатель переменной. Если вы действительно хотите это сделать, передайте делегата.

На самом деле есть один язык .NET, который его поддерживает, VB.NET генерирует такой код:

  T temp = obj->prop;
  func(temp)
  obj->prop = temp;

Однако существует ужасная проблема с псевдонимами, совершенно не поддающаяся отладке. Это идет наперекосяк в (редком) случае, когда функция func() также использует это свойство. В противном случае вы бы обошли ограничение явно в своем собственном коде.

Остерегайтесь того, что ваш код неверен, возможно, преднамеренно, вы передаете C++ & ссылку, а не управляемый % внутренний указатель. Компилятор будет жаловаться на это, вы не можете создавать ссылки или указатели на управляемые объекты. Они двигаются. Если только ссылка не относится к переменной в стеке. В противном случае это не меняет ответ.

person Hans Passant    schedule 01.04.2011
comment
Спасибо за информацию. Я не писал исходный код, не думаю, что & был обязательно преднамеренным, но этот пример компилируется без предупреждений. Не помечая как ответ, потому что я скрестил пальцы, что есть решение :) - person Thomas; 01.04.2011
comment
Если вы не думаете, что это ответ, то я очень плохо объяснил, почему это невозможно. Тогда не стоит отмечать это как ответ. - person Hans Passant; 01.04.2011
comment
Что ж, моя надежда основывалась на получении доступа к функции Set, что, как я теперь уверен, невозможно. - person Thomas; 01.04.2011

Для тех, кто может оказаться здесь, задаваясь вопросом, как я справился с этим, мне повезло, что класс, с которым я работал, был сущностью LLBLGen, поэтому я смог заменить

unset(re->var);

с

{  SD::LLBLGen::Pro::ORMSupportClasses::IEntityField2^ f = re->Fields[#var]; \
   if (f->IsNullable) \
       f->CurrentValue = nullptr; }
person Thomas    schedule 13.04.2011