Спасибо, Грэг, за ваш ответ, который происходит так, как вы его описываете. Тем не менее, я не доволен этой ситуацией, потому что это означает, что я должен разместить
if(this == nullptr) throw gcnew ArgumentException("this");
в начале каждого метода. Только это гарантирует, что мой метод не будет отображаться в верхней части трассировки стека как неисправный фрагмент кода без проверки аргументов.
Я никогда не сталкивался (это == ноль), когда я писал на C #. Поэтому я решил выяснить, чем он отличается от C ++ / CLI. Я создал пример приложения в C ++ / CLI:
namespace ThisEqualsNull{
public ref class A
{
public:
void SampleMethod()
{
System::Diagnostics::Debug::Assert(this != nullptr);
}
};
public ref class Program{
public:
static void Main(array<System::String ^> ^args)
{
A^ a = nullptr;
a->SampleMethod();
}
};
}
И небольшая программа на C #, которая использует классы C ++ / CLI с тем же методом Main:
class Program
{
static void Main(string[] args)
{
A a = null;
a.SampleMethod();
}
}
Затем я разобрал их с помощью .NET Reflector от Red Gate:
C++/CLI
.method public hidebysig static void Main(string[] args) cil managed
{
.maxstack 1
.locals ( [0] class ThisEqualsNull.A a)
L_0000: ldnull
L_0001: stloc.0
L_0002: ldnull
L_0003: stloc.0
L_0004: ldloc.0
L_0005: call instance void ThisEqualsNull.A::SampleMethod()
L_000a: ret
}
C#
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 1
.locals init ( [0] class [ThisEqualsNull]ThisEqualsNull.A a)
L_0000: nop
L_0001: ldnull
L_0002: stloc.0
L_0003: ldloc.0
L_0004: callvirt instance void [ThisEqualsNull]ThisEqualsNull.A::SampleMethod()
L_0009: nop
L_000a: ret
}
Важными частями являются:
C++/CLI
L_0005: call instance void ThisEqualsNull.A::SampleMethod()
C#
L_0004: callvirt instance void [ThisEqualsNull]ThisEqualsNull.A::SampleMethod()
Где:
- call - вызывает метод, указанный переданным дескриптором метода.
- callvirt - вызывает метод с поздней привязкой для объекта, помещая возвращаемое значение в стек оценки.
А теперь окончательный вывод:
Компилятор C # в VS 2008 рассматривает каждый метод как виртуальный, поэтому всегда можно предположить, что это (this! = Null). В C ++ / CLI каждый метод вызывается так, как следует, поэтому необходимо обращать внимание на вызовы не виртуальных методов.