泛型子类与类型推断——这是唯一实现方式吗?
当然不是啦!你用非泛型基类+泛型子类的方式来实现成功/失败模型是完全可行的,但实际上还有不少其他方案可以达到类似的效果,甚至在某些场景下更简洁灵活。
下面给你列举几种常见的替代实现方式:
1. 泛型约束+静态工厂方法
这种方式通过一个统一的泛型结果类,配合私有构造函数和静态工厂方法来创建实例,编译器能自动根据返回值推断类型,代码也更紧凑:
public class Result<T> { public bool IsSuccess { get; } public T? Value { get; } public string? ErrorMessage { get; } // 私有构造函数,强制通过工厂方法创建实例 private Result(bool isSuccess, T? value, string? errorMessage) { IsSuccess = isSuccess; Value = value; ErrorMessage = errorMessage; } // 成功结果工厂方法 public static Result<T> Success(T value) => new Result<T>(true, value, null); // 失败结果工厂方法 public static Result<T> Failure(string errorMessage) => new Result<T>(false, default, errorMessage); }
调用时直接通过静态方法生成实例,类型推断会自动生效:
var successRes = Result<int>.Success(100); var failRes = Result<string>.Failure("参数错误");
2. 辨别联合(Discriminated Unions)
从C# 9.0开始支持的record类型+辨别联合,完全贴合函数式编程的成功/失败模型,模式匹配时格外方便,类型推断也非常友好:
// 抽象基类 public abstract record Result; // 成功结果,携带泛型返回值 public record SuccessResult<T>(T Value) : Result; // 失败结果,携带错误信息 public record FailureResult(string ErrorMessage) : Result; // 使用示例 Result FetchData(bool isSuccess) { return isSuccess ? new SuccessResult<int>(200) : new FailureResult("请求超时"); } // 模式匹配处理结果 var result = FetchData(true); if (result is SuccessResult<int> success) { Console.WriteLine($"成功:{success.Value}"); } else if (result is FailureResult fail) { Console.WriteLine($"失败:{fail.ErrorMessage}"); }
3. 泛型接口+隐式转换
通过定义泛型接口,分别实现成功/失败的具体类,再添加隐式转换操作符,让调用代码更直观,编译器会自动完成类型推断:
public interface IResult<T> { bool IsSuccess { get; } T? Value { get; } string? ErrorMessage { get; } } public class Success<T> : IResult<T> { public bool IsSuccess => true; public T Value { get; } public string? ErrorMessage => null; public Success(T value) => Value = value; // 隐式转换:从泛型值直接转为Success实例 public static implicit operator Success<T>(T value) => new Success<T>(value); } public class Failure<T> : IResult<T> { public bool IsSuccess => false; public T? Value => default; public string ErrorMessage { get; } public Failure(string errorMessage) => ErrorMessage = errorMessage; // 隐式转换:从错误信息字符串直接转为Failure实例 public static implicit operator Failure<T>(string errorMessage) => new Failure<T>(errorMessage); }
调用时可以直接赋值,不需要显式声明类型:
IResult<int> res1 = 200; // 自动转为Success<int> IResult<int> res2 = "数据库连接失败"; // 自动转为Failure<int>
这些方案各有优劣:辨别联合更符合现代函数式编程风格,静态工厂方法兼容性更好(支持旧版C#),隐式转换则让调用代码更简洁。你可以根据项目的C#版本、团队习惯以及实际需求来选择合适的实现方式~
内容的提问来源于stack exchange,提问作者user9993
相关产品推荐
相关产品推荐

