Reputation: 111
I usually check nullable types with if (foo is not null)
, and afterwards I can use foo
like the non-null type. Why doesn't this work with structs? Even the !
operator does not help. Is this a bug or am I missing something? What's the shortest workaround?
Foo? foo = new Foo { a = "foo" };
if (foo is not null) {
Console.WriteLine(foo.a); // Works, prints "foo"
}
Bar? bar = new Bar { a = "bar" };
if (bar is not null) {
Console.WriteLine(bar.a); // Error: Bar? does not contain a definition for "a"
Console.WriteLine(bar!.a); // Same error
}
class Foo {
public string a;
}
struct Bar {
public string a;
}
Upvotes: 1
Views: 965
Reputation: 172448
Backwards-compatibility.
Nullable value types exist since C# 2.0, and they are implemented differently than nullable reference types (since C# 8.0).
int?
is a synonym for Nullable<int>
, which is a completely different type than int
. There is some compiler magic (lifted operators) to make it behave similarly, but Nullable<int>
has members that int
doesn't have (HasValue
, Value
) and vice-versa (ToString(string)
).string?
on the other hand, is of type string
, with additional compile-time checks enabled.Making a null-check on int?
allow you to access the underlying int
without "unwrapping" it with .Value
would have broken tons of existing code.
You can, however, use pattern matching to create a new variable with the underlying type:
int? a = 3; // implicit conversion from int to Nullable<int>
if (a is int b)
{
// Use b to access the underlying int here.
}
else
{
// a was null
}
Upvotes: 4
Reputation: 473
Structs are value types and cannot be assigned to null. By declaring the struct as nullable you wrap them in a Nullable<T> struct. You should check the HasValue and Value property of the Nullable<Bar> struct in you case.
Bar? bar = new Bar { a = "bar" };
if (bar.HasValue)
{
Console.WriteLine(bar.Value.a);
Console.WriteLine(bar.Value.a);
}
Upvotes: 2
Reputation: 21
A struct is a value type so it's never null. You can check the default value for struct
Upvotes: 1