Reputation: 28618
I'm curious about how nullable reference types work, not in your own codebase, but with an already compiled library. Will C# be able to know if a property or parameter is nullable, perhaps checking the existance of some compiler-added attribute?
Upvotes: 6
Views: 2971
Reputation: 1503090
It looks like the behaviour has changed between VS2019 Preview 1 and Preview 2, potentially due to the way that the nullable context can be changed. There's no longer a per-assembly or per-type attribute. It's possible it'll change again, of course,
In VS2019 Preview 2, each part of a member that expresses either nullable or non-nullable information (parameters and return type) is separately attributed using a NullableAttribute
which is included in the assembly itself if necessary. This attribute has two constructors:
NullableAttribute(byte)
NullableAttribute(byte[])
The byte
form is used when every aspect of the nullability for that parameter/return type is the same. The byte[]
is used when there's a mixture of nullability for a single element, due to generics or arrays. In both cases, 1 is used for "not-nullable", 2 is used for "nullable". So for example:
public class Test
{
public string? Foo(string input) { ... }
public List<string>? Bar() { ... }
}
is compiled to:
public class Test
{
[return:Nullable(2)]
public string Foo([Nullable(1)] string input) { ... }
[return: Nullable(new byte[] { 1, 2 })]
public List<string> Bar() { ... }
}
This allows any code examining the assembly (whether that's the compiler using it as a reference, or other tooling) to understand the intention on a per-member basis.
I've written more about this in a blog post but that should be enough to get the gist.
Upvotes: 7
Reputation: 244988
Yes, if the library has been compiled using a C# 8.0 compiler with nullable reference types turned on, the compiler will be able to recognize which values were marked as nullable.
For example, consider this code:
class C
{
string NotNullProperty { get; set; }
string? NullProperty { get; set; }
void M(string notNullParameter, string? nullParameter) {}
}
[NonNullTypes(true)]
class C
{
string NotNullProperty { get; set; }
[Nullable]
string NullProperty { get; set; }
void M(string notNullParameter, [Nullable] string nullParameter) { }
}
Notice that the nullable property and parameter are marked as [Nullable]
and that the whole class is marked as [NonNullTypes(true)]
, indicating that the nullable reference types feature is enabled for it.
On the other hand, if the code was compiled without the feature, it will be considered "null-oblivious". This means that the compiler will not produce null-related warnings when you're working with that code.
Upvotes: 6
Reputation: 32702
In Take C# 8.0 for a spin by Mads Torgersen (Program Manager for the C# language at Microsoft) he says:
If you call code that didn’t have the nullable reference types feature on (maybe it was compiled before the feature even existed), then we cannot know what the intent of that code was: it doesn’t distinguish between nullable and nonnullable – we say that it is "null-oblivious". So we give it a pass; we simply don’t warn on such calls.
So no, it appears they won't flag it, so you won't get any sort of compiler warning. So when consuming code prior to C# 8, it seems like you'll have to do some research to find out whether the reference could contain null or not, instead of relying on the type system and compiler to warn you.
Upvotes: 1