Are there any public MemberNotNull/MemberNotNullWhen attributes in .net core

4.1k Views Asked by At

I have read the following article about nullable reference analysis in C# 8 not long ago: https://www.meziantou.net/csharp-8-nullable-reference-types.htm

The post-condition attributes are particularly interesting to me. Recently I have encountered a situation where it might be useful to apply MemberNotNull attribute. However, unexpectedly I can't find MemberNotNull and MemberNotNullWhen public attributes in the .Net core 3.1. However, I can see a number of internal attributes declared in .net core: https://source.dot.net/#q=MemberNotNull

Are there any substitutions in .net core for these attributes. Do I have to use .net 5 to use them?

4

There are 4 best solutions below

1
On BEST ANSWER

You can reference Nullable package. It will do basically the same as you did with copy-paste. Think that's the best way to backport these attributes to pre .net50 sdks.

1
On

I tried to copy declarations of both attributes to my source code but it didn't help when I declared attributes in my custom namespace. However if I declare them in System.Diagnostics.CodeAnalysis namespace like this then it works:

namespace System.Diagnostics.CodeAnalysis
{
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
    public sealed class MemberNotNullWhenAttribute : Attribute
    {
        /// <summary>Initializes the attribute with the specified return value condition and a field or property member.</summary>
        /// <param name="returnValue">
        /// The return value condition. If the method returns this value, the associated parameter will not be null.
        /// </param>
        /// <param name="member">
        /// The field or property member that is promised to be not-null.
        /// </param>
        public MemberNotNullWhenAttribute(bool returnValue, string member)
        {
            ReturnValue = returnValue;
            Members = new[] { member };
        }

        /// <summary>Initializes the attribute with the specified return value condition and list of field and property members.</summary>
        /// <param name="returnValue">
        /// The return value condition. If the method returns this value, the associated parameter will not be null.
        /// </param>
        /// <param name="members">
        /// The list of field and property members that are promised to be not-null.
        /// </param>
        public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
        {
            ReturnValue = returnValue;
            Members = members;
        }

        /// <summary>Gets the return value condition.</summary>
        public bool ReturnValue { get; }

        /// <summary>Gets field or property member names.</summary>
        public string[] Members { get; }
    }
}

And Roslyn removes the displayed warning for possible null dereference. However, instead I receive the following error:

Error CS8652: The feature 'MemberNotNull attribute' is currently in Preview and unsupported. To use Preview features, use the 'preview' language version.

So it seems I can at least switch to the preview language version with this approach. But I would like to avoid such hacks, so if there is a better solution please provide it and I will mark it as an accepted answer.

EDIT: To avoid some confusion expressed in the comments - this answer allows to use MemberNotNullWhen attribute without compile time error. Just add

  <LangVersion>preview</LangVersion>

to your project file.

0
On

If you do not want to upgrade your framework version, or backport support for [MemberNotNull] from .NET 5, you can instead initialize the relevant fields using the null forgiving operator as a workaround.

For example, if you have a non-nullable field _myField that is initialized in the method Init(), you can add write the following in your constructor to remove the warning about a non-null value when exiting the constructor.

_myField = null!;
InitFields();
0
On

Recently I have found the PolySharp project that allows to add all modern C# features that do not not require runtime support to solutions targeting older .Net frameworks: https://github.com/Sergio0694/PolySharp

This includes the attributes provided by the Nullable package mentioned in the @unsafePtr answer but also init and required property accessors, records and many other things.

I've decided to add the link to the PolySharp project as a different answer because I feel that it's a different kind of answer from the manual implementation I have specified before.