在 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] 删除。
我来说两句