如何在 Visual Studio 2022 和 .net Standard 2.0 或 .net 4.8 中使用 CallerArgumentExpression?

馬修·沃森

在 Visual Studio 2022 和 .net 6.0 中,我們有了新的CallerArgumentExpression屬性,可用於“捕獲傳遞給方法的表達式,以在診斷/測試 API 中啟用更好的錯誤消息並減少擊鍵次數”

例如,我們可以編寫一個類來檢查空方法參數,如下所示:

public static class Contract
{
    public static T RequiresArgNotNull<T>(T? item, [CallerArgumentExpression("item")] string? expression = default, string? message = null)
        where T : class
    {
        if (item == null)
            throw new ArgumentNullException(
                expression ?? "<unknown>",
                message ?? (expression != null ? "Requires " + expression + " != null" : "RequiresArgNotNull() failed."));

        return item;
    }
}

可以這樣使用:

using static ClassLibrary1.Contract; // To allow just putting RequiresArgNotNull()

...

static void test(string theString)
{
    RequiresArgNotNull(theString); // Note that we do NOT need to pass the parameter
                                   // name as a separate string.
    Console.WriteLine(theString);
}

如果theString為空,則會拋出異常,如下所示:

System.ArgumentNullException: Requires theString != null
Parameter name: theString

我希望能夠在 .net 4.8 和/或 .net Standard 2.0 中使用此功能。這可能嗎?

馬修·沃森

如果您使用的是 Visual Studio 2022,則可以CallerArgumentExpression通過定義如下本地internal實現來與 .net 4.8 和/或 .net Standard 2.0 一起使用CallerArgumentExpressionAttribute

namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
    internal sealed class CallerArgumentExpressionAttribute : Attribute
    {
        public CallerArgumentExpressionAttribute(string parameterName)
        {
            ParameterName = parameterName;
        }

        public string ParameterName { get; }
    }
}

請注意,您必須使用System.Runtime.CompilerServices命名空間才能使其正常工作。通過進行此實現,internal您可以保證它不會與任何系統定義的實現發生衝突。

這將編譯為.net Standard 2.0目標,因此它也可以被目標程序集使用.net 4.8.net Core 3.1等等。

另請注意,您仍然需要 Visual Studio 2022 及其 SDK 才能正常工作 - 如果您嘗試使用 Visual Studio 2019,它將編譯正常,但參數將為空。

您可以在使用的程序集中包含上述類,CallerArgumentExpression它將按預期工作。


示例 .net Standard 2.0 類庫提供Contract.RequiresArgNotNull()

ClassLibrary1為簡潔起見,此示例程序集使用命名空間。)

項目:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <LangVersion>8</LangVersion>
  </PropertyGroup>

</Project>

CallerArgumentExpression.cs:

namespace System.Runtime.CompilerServices
{
    #if !NET6_0_OR_GREATER

    [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
    internal sealed class CallerArgumentExpressionAttribute : Attribute
    {
        public CallerArgumentExpressionAttribute(string parameterName)
        {
            ParameterName = parameterName;
        }

        public string ParameterName { get; }
    }

    #endif
}

合同.cs:

using System;
using System.Runtime.CompilerServices;

#nullable enable

namespace ClassLibrary1
{
    public static class Contract
    {
        public static T RequiresArgNotNull<T>(T? item, [CallerArgumentExpression("item")] string? expression = default, string? message = null)
            where T : class
        {
            if (item == null)
                throw new ArgumentNullException(
                    expression ?? "<unknown>",
                    message ?? (expression != null ? "Requires " + expression + " != null" : "RequiresArgNotNull() failed."));

            return item;
        }
    }
}

演示使用的示例控制台應用程序RequiresArgNotNull()

using System;
using static ClassLibrary1.Contract;

#nullable enable

namespace Demo
{
    class Program
    {
        static void Main()
        {
            try
            {
                test(null!);
            }

            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());   
            }
        }

        static void test(string theString)
        {
            RequiresArgNotNull(theString);
            Console.WriteLine(theString);
        }
    }
}

這將輸出以下異常消息(對於我的特定構建):

System.ArgumentNullException: Requires theString != null
Parameter name: theString
   at ClassLibrary1.Contract.RequiresArgNotNull[T](T item, String expression, String message) in E:\Test\cs9\ConsoleApp1\ClassLibrary1\Contract.cs:line 18
   at Demo.Program.test(String theString) in E:\Test\cs9\ConsoleApp1\ConsoleApp1\Program.cs:line 25
   at Demo.Program.Main() in E:\Test\cs9\ConsoleApp1\ConsoleApp1\Program.cs:line 14

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在WinForm和C#(Visual Studio 2015)中使用.Net Native?

如何在.NET Core,C#6和Visual Studio 2015中使用本地IIS?

.NET 4.5 项目未在 Visual Studio 2022 中编译

如何在Visual Studio 2012上使用ASP.NET(包含MVC)C#配置或设置Log4Net

如何在Visual Studio ASP.NET Core项目中使用语义UI反应?

如何在Visual Studio测试中使用ASP.NET Core环境变量

如何在典型的.NET / Visual Studio工作流程中使用Bower?

如何在Visual Studio 2019中使用.NET 4.6.2版运行单元测试?

如何在visual studio中使用.NET中的控制台代码

如何在不让用户登录的情况下跟踪他们的信息(在Visual Studio中使用asp.net mvc4)

如何在.NET Standard库中使用Sqlite?

在没有Visual Studio的情况下使用.NET Framework 4.6.1构建.NET Standard Library 1.4

指定 C++20 時無法在 Visual Studio 2022 中使用 CA2CT 和 CW2T

通過 Visual Studio 2022 使用 C# 10 隱式使用發布 .NET 6 項目

使用Visual Studio和.NET进行Angular 2路由

更新,编辑,删除和导入文件。javascript。在Visual Studio中使用ASP:.NET MVC C#

Visual Studio 2022 - Visual Basic ASP.NET Web 應用程序

使用Visual Studio和.NET Framework进行多目标构建

使用Connector / NET和Visual Studio 2013 Express引用MySQL

使用Visual Studio和Asp.Net Core的Dockerfile错误

如何在.NET Standard 2.0 / Core 2.1中使用PrivateKey创建X509Certificate2?

如何在Visual Studio 2015中创建ASP.NET MVC 4项目

如何在Asp.net Web Api 2中使用多种Put和Post方法

如何在Visual Studio中发布.net核心项目,包括视图和区域文件夹

如何使用.NET Core 3和Visual Studio创建WPF应用

如何使用Visual Studio Online和.NET Desktop App进行文件转换/变量替换

如何在Visual Studio中使用ASP.NET Core Web应用程序-API项目托管网页?

如何在Visual Studio 2019中使用Entity Framework Core将实体模型添加到.Net Core ClassLibrary?

如何在带有Polymer的Visual Studio ASP.NET Core应用程序中使用照明元素