Does C# 8 annotate nullable properties and parameters?
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.
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) {}
}
It compiles roughly into:
[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.