SW 随笔 007 — C# 10/.NET6 CallerArgumentExpression 案例
声明:个人笔记,概不负责
参考文章: .NET6新东西--CallerArgumentExpression
参考摘要:
在.NET6以前我们如果要获取调用方的信息可以使用这三个Caller Info Attribute:
- CallerMemberName:调用方名称,方法名或者属性名;
- CallerFilePath:调用方源代码的位置;
- CallerLineNumber:调用方位于源代码的第几行。
- 新增的CallerArgumentExpression也是一种caller info,一般会用它来自动获取传进来的参数表达式
本文开始:
上文中的例子实在没有说服力,官方英文文档[1] 也实在是没看懂。官方实际的人话在这里[2]
| Attribute | Description | Type |
|---|---|---|
| CallerArgumentExpressionAttribute | String representation of the argument expression. | String |
经过和 Copilot 反复掰扯,实际意思如下, …… 上代码!
class DemoBoard
{
// C# 10/.NET 6 get the argument expression (实参表达式) for parameter (形参)
//
// 英文里, argument 表示 "实参"
// parameter 表示 "形参"
//
public static byte SlaveAddr(
object? dummy, // parameter (形参)
[CallerArgumentExpression(nameof(dummy))] string? argExpr = null // 捕获 argument (实参)
)
{
Debug.WriteLine(argExpr);
byte addr = 1;
return addr;
// 从 实参 推算 另一个值, 可以用 Attribute 反射, 也可以用 查表, .. (随心所欲)
//
// addr = GetAddressFromAttribute(argExpr)
}
public DemoBoard()
{
IoExp = new IoExpander(SlaveAddr(IoExp)); // argument (实参) 为 IoExp
IoExp2 = new IoExpander(SlaveAddr(this.IoExp2)); // argument (实参) 为 this.IoExp2
// 为什么是 argument expression (实参表达式) ?
//
// 因为 caller 可以在 形参 的位置, 传入表达式
//
// 所以, [CallerArgumentExpression] 类似某种 源代码级 的反射
// 可以 倒吐出 形参 位置, 实际填充的 源代码
//
// 所以, [CallerArgumentExpression] 标注的类型为 string
//
// 所以, 实际在处理 argExpr 时, 需要 防御式 清理字符串
// 因为, 主要是 源自帮助 Debug 目的这一脉,
// 所以, 也不用太激动, 洒洒水(大概) 防御一下就行. 你又不是写编译器, 你看看它的全名
//
// System.Runtime.CompilerServices.CallerArgumentExpressionAttribute
//
}
// 此处用 Attribute 注入,帅的一逼啊
//
[Slave7bitAddress(0x20, "[U1004] 7bitAddress = 0x20 | Write= 0x40 | Read= 0x41")]
readonly IoExpander IoExp;
[Slave7bitAddress(0x21, "[U1005] 7bitAddress = 0x21 | Write= 0x42 | Read= 0x43")]
readonly IoExpander IoExp2;
}
class IoExpander
{
public IoExpander(byte Addr)
{
}
}
浙公网安备 33010602011771号