如何将 CallerArgumentExpression 与 Visual Studio 2022 和 .net Standard 2.0 或 .net 4.8 一起使用?
How can I use CallerArgumentExpression with Visual Studio 2022 and .net Standard 2.0 or .net 4.8?
有了 Visual Studio 2022 和 .net 6.0,我们有了新的 CallerArgumentExpression
attribute 可以用来 " 捕获传递给方法的表达式,以便在diagnostic/testing API 并减少击键次数。
例如,我们可以编写一个 class 来检查空方法参数,如下所示:
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
为 null,将抛出如下所示的异常:
System.ArgumentNullException: Requires theString != null
Parameter name: theString
我希望能够在 .net 4.8 and/or .net Standard 2.0 中使用此功能。这可能吗?
如果您使用 Visual Studio 2022,您可以通过定义 internal
的本地 internal
实现,将 CallerArgumentExpression
与 .net 4.8 and/or .net Standard 2.0 一起使用18=] 像这样:
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,它将编译正常,但参数将为空。
您可以将上述 class 包含在使用 CallerArgumentExpression
的程序集中,它将按预期工作。
示例 .net Standard 2.0 class 库提供 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
}
Contract.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
有了 Visual Studio 2022 和 .net 6.0,我们有了新的 CallerArgumentExpression
attribute 可以用来 " 捕获传递给方法的表达式,以便在diagnostic/testing API 并减少击键次数。
例如,我们可以编写一个 class 来检查空方法参数,如下所示:
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
为 null,将抛出如下所示的异常:
System.ArgumentNullException: Requires theString != null
Parameter name: theString
我希望能够在 .net 4.8 and/or .net Standard 2.0 中使用此功能。这可能吗?
如果您使用 Visual Studio 2022,您可以通过定义 internal
的本地 internal
实现,将 CallerArgumentExpression
与 .net 4.8 and/or .net Standard 2.0 一起使用18=] 像这样:
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,它将编译正常,但参数将为空。
您可以将上述 class 包含在使用 CallerArgumentExpression
的程序集中,它将按预期工作。
示例 .net Standard 2.0 class 库提供 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
}
Contract.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