【问题标题】:Are there any public MemberNotNull/MemberNotNullWhen attributes in .net core.net 核心中是否有任何公共 MemberNotNull/MemberNotNullWhen 属性
【发布时间】:2020-11-23 20:30:36
【问题描述】:

我不久前读过以下关于 C# 8 中可空引用分析的文章: https://www.meziantou.net/csharp-8-nullable-reference-types.htm

后置条件属性对我来说特别有趣。最近我遇到了一种情况,应用MemberNotNull 属性可能很有用。但是,出乎意料的是,我在 .Net core 3.1 中找不到 MemberNotNullMemberNotNullWhen 公共属性。但是,我可以看到 .net 核心中声明的许多内部属性: https://source.dot.net/#q=MemberNotNull

.net 核心中是否有这些属性的替换。我必须使用 .net 5 才能使用它们吗?

【问题讨论】:

  • MemberNotNullWhenAttribute 被添加到 .NET 5 中,源代码可以在 here 找到。
  • MemberNotNull可以在the same file找到
  • 感谢您提供文档链接。我自己在问题中提供了指向 MemberNotNullWhenAttribute 来源的链接。在 .net core 的不同程序集中有多个相同属性的声明。如果可能的话,我想在我的代码中避免这样的声明,因为它对我来说看起来不是很干净。更重要的是,我不知道它是否适用于 Roslyn。
  • 我尝试将这两个属性的声明复制到我的代码中,但没有成功。警告仍然显示。
  • 嗯,这很明显。属性本身不做任何事情。您还需要工具(Roslyn 分析器)

标签: c# c#-8.0 nullable-reference-types


【解决方案1】:

您可以参考Nullable 包。它的作用与复制粘贴基本相同。认为这是将这些属性反向移植到 .net50 之前的 sdks 的最佳方式。

【讨论】:

  • Init polyfill 是同一作者
【解决方案2】:

我尝试将这两个属性的声明复制到我的源代码中,但是当我在自定义命名空间中声明属性时它没有帮助。但是,如果我像这样在 System.Diagnostics.CodeAnalysis 命名空间中声明它们,那么它可以工作:

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; }
    }
}

Roslyn 删除了可能的 null 取消引用显示的警告。 但是,我收到以下错误:

错误 CS8652:功能“MemberNotNull 属性”当前处于预览状态且不受支持。要使用预览功能,请使用“预览”语言版本。

所以看来我至少可以用这种方法切换到预览语言版本。但我想避免这种黑客攻击,所以如果有更好的解决方案,请提供,我会将其标记为已接受的答案。

编辑:为了避免在 cmets 中表达的一些混淆 - 这个答案允许使用 MemberNotNullWhen 属性而不会出现编译时错误。只需添加

  <LangVersion>preview</LangVersion>

到您的项目文件。

【讨论】:

  • 如果您切换到我描述的语言版本“预览”,这不会导致编译时错误。请把答案读到最后。
【解决方案3】:

如果您不想升级您的框架版本,或从 .NET 5 向后移植对 [MemberNotNull] 的支持,您可以使用 null 宽恕运算符来初始化相关字段作为解决方法。

例如,如果您有一个在方法Init() 中初始化的不可空字段_myField,则可以在构造函数中添加以下内容,以删除退出构造函数时有关非空值的警告.

_myField = null!;
InitFields();

【讨论】:

    猜你喜欢
    • 2021-08-13
    • 1970-01-01
    • 2017-06-21
    • 1970-01-01
    • 1970-01-01
    • 2011-04-03
    • 1970-01-01
    • 2022-07-01
    • 1970-01-01
    相关资源
    最近更新 更多