We're verifying that method arguments aren't null upon function entry, but this doesn't work for Platform::String
(or Platform.String
, no difference between C# or C++), since they overload the semantics of an empty string with a null instance.
Consider this, where the exception will always be thrown:
auto emptyString = ref new Platform::String();
// Now, emptyString.IsEmpty() will be true
if (emptyString == nullptr)
{
throw ref new Platform::InvalidArgumentException();
}
The variable has a non-null value, but the ==
comparison operator is overloaded so comparing it to nullptr
returns true since the String
instance is empty.
As far as I can see this makes it impossible for us to make proper null checks at function entry for String
s. Is that really so?
There are no "null strings" in Windows Runtime. "Null" and "empty" mean the same thing with respect to strings.
Despite the fact that Platform::String
uses the ^
syntax and looks like a reference type, it's not: it's a projection of a Windows Runtime fundamental type, HSTRING
. A "null" HSTRING is indistinguishable from an empty HSTRING.
Even if a Platform::String^
appears to be "null" (e.g. in the debugger), it is safe to treat it as if it were an empty string. You can use it for concatenation, call s->Length()
, etc.
In C#, a string
can be null (and you can thus test it for null), but you will never get a null string
from a Windows Runtime call and you cannot pass a null string as an argument to a Windows Runtime function (doing so will yield an exception at the ABI boundary).
Seems that you are right. Any string which is set to nullptr
is treated as an empty string. And if you even pass nullptr
to the function you will never get the NullReferenceException
.
bool NullPtrTest(Platform::String^ value)
{
return value == nullptr;
}
bool EmptyTest(Platform::String^ value)
{
return value->IsEmpty();
}
bool ReferenceEqualsWithNullPtrTest(Platform::String^ value)
{
return Platform::String::ReferenceEquals(nullptr, value);
}
bool EqualsWithValueTest(Platform::String^ value)
{
return value->Equals("test");
}
//...
NullPtrTest(nullptr); // true
NullPtrTest(ref new Platform::String()); // true
NullPtrTest("test"); // false
EmptyTest(nullptr); // true - no exception
EmptyTest(ref new Platform::String()); // true
EmptyTest("test"); // false
ReferenceEqualsWithNullPtrTest(nullptr); // true
ReferenceEqualsWithNullPtrTest(ref new Platform::String()); // true
ReferenceEqualsWithNullPtrTest("test"); // false
EqualsWithValueTest(nullptr); // false - no exception
EqualsWithValueTest(ref new Platform::String()); // false
EqualsWithValueTest("test"); // true
So, I see no way to find out whether the string was ever nullptr
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With