方法返回元组的使用痛点:寻求更优实现方案
使用返回元组替代传统错误处理方式的痛点与解决方案
背景
我尝试用返回元组的方式替代两种传统方法签名:
传统写法1:
private int GetAlpha() {...} // -1 表示错误
传统写法2:
private bool GetAlpha(out int alphaOut) {...}
改为元组返回:
private (bool Success, int Alpha) GetAlpha() {...}
这种方式的优势
- 避免用-1这类带外值传递错误信号
- 规避不推荐使用的
out参数
存在的弊端
- 方法内
var (success, a, b, ...) = Foo(...)这种解构语法通常只能用一次,后续因为success已定义,必须声明返回元组的几乎所有变量 - 后续使用时必须显式指定变量类型,无法再用
var做隐式类型推断
示例代码:
var (success, alpha) = GetAlpha(); if (success) { //var (success, beta, gamma) = GetStuff(alpha); // 错误 - 'success' 已定义 //(success, beta, gamma) = GetStuff(alpha); // 错误 - 'beta' 和 'gamma' 未定义 //(success, var beta, var gamma) = GetStuff(alpha); // 错误 - 无此语法! string beta; DateTime gamma; (success, beta, gamma) = GetStuff(alpha); // ... }
我很喜欢这种隐式声明和类型推断的便捷性,但只能用一次这点让人困扰。请问有没有遗漏什么技巧?或者其他模式可以解决这个问题?
解决方案
1. 利用局部作用域隔离变量
把后续的调用放在单独的代码块({})里,这样就能重新使用var解构,变量作用域被限制在块内,不会和外部的success冲突:
var (success, alpha) = GetAlpha(); if (success) { { var (successInner, beta, gamma) = GetStuff(alpha); if (successInner) { // 处理beta和gamma } } // 这里可以继续使用外部的success,不受内部变量影响 }
2. 重新命名解构变量
直接给后续的success换个名字,避免重复定义问题,同时依然能使用var推断类型:
var (success, alpha) = GetAlpha(); if (success) { var (successGetStuff, beta, gamma) = GetStuff(alpha); if (successGetStuff) { // 处理逻辑 } }
这种方式更直观,变量名能体现具体操作的成功状态,可读性反而更强。
3. 直接访问元组的属性
不使用解构,而是直接将元组赋值给变量,通过属性访问结果,这样也能避免变量重复定义的问题:
var alphaResult = GetAlpha(); if (alphaResult.Success) { var stuffResult = GetStuff(alphaResult.Alpha); if (stuffResult.Success) { var beta = stuffResult.Beta; var gamma = stuffResult.Gamma; // 处理逻辑 } }
这种写法虽然少了解构的简洁,但变量语义清晰,也不会有重复定义的问题。
4. 自定义结果类型(推荐)
如果这类结果返回的场景较多,可以定义一个通用的泛型结果类,替代元组,既保留类型安全,又能灵活处理:
public class Result<T> { public bool Success { get; } public T Value { get; } public Result(bool success, T value) { Success = success; Value = value; } } // 多返回值版本 public class Result<T1, T2> { public bool Success { get; } public T1 Value1 { get; } public T2 Value2 { get; } public Result(bool success, T1 value1, T2 value2) { Success = success; Value1 = value1; Value2 = value2; } }
使用时:
var alphaResult = GetAlpha(); // 方法返回Result<int> if (alphaResult.Success) { var stuffResult = GetStuff(alphaResult.Value); // 返回Result<string, DateTime> if (stuffResult.Success) { var beta = stuffResult.Value1; var gamma = stuffResult.Value2; // 处理逻辑 } }
这种方式扩展性更强,还能在结果类中添加错误信息等额外字段,比元组更灵活。
内容的提问来源于stack exchange,提问作者Scott Smith
相关产品推荐
相关产品推荐

