是否可以在 .NET Framework 4.8 和 .Net Standard 2.0 中使用 C#11“required”修饰符?

Mat*_*son 18 .net c#

我希望能够将新的 C#11required修饰符与 .NET Framework 4.8 和 .Net Standard 2.0 一起使用。

我使用的是 Visual Studio 2022 版本 17.4。这可能吗?

Mat*_*son 32

这是可能的,但您必须提供编译器需要的一些类型才能支持它。您还需要使用 Visual Studio 2022 版本 17.4 或更高版本以及 C# 11 进行编译。

.NET 7.0 中定义了必要的类型,但早期版本中并不全部存在。这些类型如下:

  • static class IsExternalInit- 随 C# 9 和 .NET 5 引入。
  • class RequiredMemberAttribute- 随 C# 11 和 .NET 7 引入。
  • class CompilerFeatureRequiredAttribute- 随 C# 11 和 .NET 7 引入。

这些类型都必须在命名空间内定义System.Runtime.CompilerServices。它们还应该声明为internal- 如果它们是public在 .NET 7 项目引用的类库中定义的,您将收到多重定义的错误。

您可以按如下方式声明它们 - 这必须包含在使用修饰符的每个 .NET 4.8 或 .NET Standard 2.0 程序集中required

using System.ComponentModel;

namespace System.Runtime.CompilerServices
{
#if !NET5_0_OR_GREATER

    [EditorBrowsable(EditorBrowsableState.Never)]
    internal static class IsExternalInit {}

#endif // !NET5_0_OR_GREATER

#if !NET7_0_OR_GREATER

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
    internal sealed class RequiredMemberAttribute : Attribute {}

    [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
    internal sealed class CompilerFeatureRequiredAttribute : Attribute
    {
        public CompilerFeatureRequiredAttribute(string featureName)
        {
            FeatureName = featureName;
        }

        public string FeatureName { get; }
        public bool   IsOptional  { get; init; }

        public const string RefStructs      = nameof(RefStructs);
        public const string RequiredMembers = nameof(RequiredMembers);
    }

#endif // !NET7_0_OR_GREATER
}

namespace System.Diagnostics.CodeAnalysis
{
#if !NET7_0_OR_GREATER
    [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)]
    internal sealed class SetsRequiredMembersAttribute : Attribute {}
#endif
}
Run Code Online (Sandbox Code Playgroud)

请注意使用指令#if来支持不同的目标。

(顺便说一句,声明internal static class IsExternalInit {}还允许使用C# 9 中引入的record类型和属性设置器功能。)init only

将上述定义添加到 .NET Framework 4.8 或 .NET Standard 2.0 程序集后,您可以required在该程序集中使用修饰符,即使该程序集被另一个不支持该程序集的 .NET Framework 4.8 或 .NET Standard 2.0 程序集引用。不required提供这些定义(尽管如果您想对在该程序集中定义的类使用修饰符,您仍然需要在该其他程序集中提供定义)。

注意事项:

  • 所有使用修饰符的 .NET Framework 4.8 或 .NET Standard 2.0 程序集都required必须使用 Visual Studio 2022 版本 17.4 或更高版本进行编译。
  • 这些项目需要将语言版本指定为11latest使用<LangVersion>11</LangVersion><LangVersion>latest</LangVersion>
  • 您不应required通过 NuGet 包公开任何使用修饰符的公共类型。
  • 不支持这种方法,并且它可能会停止与未来版本一起使用(我认为这不太可能,但不可能保证它始终有效)。

参考:

  • https://www.nuget.org/packages/PolySharp/ 涵盖了这一点吗? (6认同)