如何实现字符串隐式转换为带CallerArgumentExpression的KeyValue类?
问题分析与解决方案
你当前的隐式转换无法获取原变量名,核心原因是:构造函数的[CallerArgumentExpression]捕获的是隐式转换方法内部的参数名,而非用户代码里的变量名。当执行KeyValue pair = ThisIsMyName;时,编译器会自动调用KeyValue.op_Implicit(ThisIsMyName),而该方法内部调用new KeyValue(value)时,构造函数捕获的是隐式转换方法里的参数名value,最终导致pair.Key输出value而非期望的变量名。
以下是两种可行的解决方案:
方案一:静态工厂方法
修改KeyValue类,将构造函数设为私有,新增带CallerArgumentExpression的静态工厂方法,直接捕获用户代码中的变量名:
public sealed class KeyValue { public string Key { get; set; } public object Value { get; set; } private KeyValue(object value, string keyName) { Value = value; Key = keyName; } public static KeyValue Create(object value, [CallerArgumentExpression(nameof(value))] string keyName = null) { return new KeyValue(value, keyName); } }
使用示例:
string ThisIsMyName = "Test"; KeyValue pair = KeyValue.Create(ThisIsMyName); Console.WriteLine(pair.Key); // 输出 ThisIsMyName Console.WriteLine(pair.Value); // 输出 Test // 调用HandleFailureAsync时: string test1 = "t1"; string test2 = "t2"; HandleFailureAsync(KeyValue.Create(test1), KeyValue.Create(test2));
方案二:字符串扩展方法
通过扩展方法为string类型添加转换方法,写法更简洁流畅:
public static class StringExtensions { public static KeyValue ToKeyValue(this string value, [CallerArgumentExpression(nameof(value))] string keyName = null) { return new KeyValue(value, keyName); } } // 保留原KeyValue类结构 public sealed class KeyValue(object value, [CallerArgumentExpression(nameof(value))] string keyName = null) { public string Key { get; set; } = keyName; public object Value { get; set; } = value; }
使用示例:
string ThisIsMyName = "Test"; KeyValue pair = ThisIsMyName.ToKeyValue(); Console.WriteLine(pair.Key); // 输出 ThisIsMyName // 调用HandleFailureAsync时: string test1 = "t1"; string test2 = "t2"; HandleFailureAsync(test1.ToKeyValue(), test2.ToKeyValue());
补充说明
目前无法通过纯隐式转换实现你的需求,因为隐式转换的调用链会打断CallerArgumentExpression对原变量名的捕获。上述两种方案都能在减少冗余代码的同时获取正确的变量名,其中扩展方法的写法更接近你期望的简洁风格。
内容的提问来源于stack exchange,提问作者gecapo
相关产品推荐
相关产品推荐

