Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does C# 8 annotate nullable properties and parameters?

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?

like image 641
Max Toro Avatar asked Dec 06 '18 20:12

Max Toro


People also ask

How long can you have hep C without knowing?

Chronic liver disease in people with hepatitis C usually happens slowly, without any signs or symptoms, over several decades. Chronic hepatitis C virus infection is often not recognized until people are screened for blood donation or from an abnormal blood test found during a routine doctor's visit.

Does hep C go away?

Hepatitis C virus (HCV) causes both acute and chronic infection. Acute HCV infections are usually asymptomatic and most do not lead to a life-threatening disease. Around 30% (15–45%) of infected persons spontaneously clear the virus within 6 months of infection without any treatment.

How easy is it to get hep C?

Hepatitis C is spread only through exposure to an infected person's blood. High-risk activities include: Sharing drug use equipment. Anything involved with injecting street drugs, from syringes, to needles, to tourniquets, can have small amounts of blood on it that can transmit hepatitis C.

Does hep C treatment make you sick?

Like the other antivirals, the side effects are mild. You might have a slight headache or bellyache, or you might feel tired. Glecaprevir and pibrentasvir (Mavyret): Three pills daily can treat all types of hep C. Side effects are mild and can include headache, fatigue, diarrhea, and nausea.


3 Answers

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.

like image 138
Jon Skeet Avatar answered Nov 14 '22 22:11

Jon Skeet


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.

like image 22
svick Avatar answered Nov 14 '22 23:11

svick


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.

like image 25
mason Avatar answered Nov 14 '22 22:11

mason