系统要求方法都返回 Result 结果,通常我们会如此定义一个 Result
1 public class Result<T> 2 { 3 public virtual int Code { get; set; } 4 5 public virtual T Data { get; set; } 6 7 public virtual string Message { get; set; } 8 } 9 10 public class Result : Result<object> 11 { 12 // 快速创建成功结果 13 public static Result<T> Success<T>(T data) 14 { 15 return new Result<T>() { Data = data }; 16 } 17 18 // 快速创建失败结果 19 public static Result<T> Fail<T>(int code, string message) 20 { 21 return new Result<T>() { Code = code, Message = message }; 22 } 23 }
得益于C#强大的类型推断,我们可以非常简单的返回成功或失败结果
1 public Result<User> GetUser(int userId) 2 { 3 User user = null; // Read from database 4 if (user == null) 5 { 6 return Result.Fail<User>(400, "用户不存在"); // 需要手动指明 User,有点烦 7 } 8 else 9 { 10 return Result.Success(user); 11 } 12 }
成功的时候,Success() 方法可以自动推断出Data为 User 类;
但是失败的时候,必须手动的指明Data为 User 类,虽然仅仅多敲了几个字母,但我还是想简化,因为失败时,Data根本不需要赋值,也不在乎Data 的类型。
C# 可以使用 Implicit 自定义隐式转换,可以将 Result 自动隐式转换转换为 Result<T>,考虑到我们只需要在失败的时候才转换,所以我定义了一个 FailResult
1 public class FailResult : Result 2 { 3 } 4 5 public class Result<T> 6 { 7 // 新增加的隐式转换 8 public static implicit operator Result<T>(FailResult failResult) 9 { 10 return new Result<T>() { Code = failResult.Code, Message = failResult.Message }; 11 } 12 } 13 14 public class Result : Result<object> 15 { 16 // 新增加的方法 17 public static FailResult Fail(int code, string message) 18 { 19 return new FailResult() { Code = code, Message = message }; 20 } 21 }
这样的话,不论时成功还是失败,我们都不需要指定Data 的类型了
1 public Result<User> GetUser(int userId) 2 { 3 User user = null; // Read from database 4 if (user == null) 5 { 6 return Result.Fail(400, "用户不存在"); // 不用指明 <User> 了 7 } 8 else 9 { 10 return Result.Success(user); 11 } 12 }
心细的朋友会发现,这种 Result.Fail 其实是先 new 一个 FailResult,然后编译器再 new 一个 Result<T>, 事实上多创建了一个无用的实例,但我觉得对于CLR而言这种开销可以忽略不记。
下面是完整的代码:
1 using System; 2 3 namespace ConsoleApp1 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 Console.WriteLine("Hello World!"); 10 } 11 12 public Result<User> GetUser(int userId) 13 { 14 User user = null; // Read from database 15 if (user == null) 16 { 17 return Result.Fail(400, "用户不存在"); // 不用指明 <User> 了 18 //return Result.Fail<User>(400, "用户不存在"); 19 } 20 else 21 { 22 return Result.Success(user); 23 } 24 } 25 } 26 27 public class Result<T> 28 { 29 public virtual int Code { get; set; } 30 31 public virtual T Data { get; set; } 32 33 public virtual string Message { get; set; } 34 35 36 public static implicit operator Result<T>(FailResult failResult) 37 { 38 return new Result<T>() { Code = failResult.Code, Message = failResult.Message }; 39 } 40 } 41 42 public class Result : Result<object> 43 { 44 public static Result<T> Success<T>(T data) 45 { 46 return new Result<T>() { Data = data }; 47 } 48 49 public static Result<T> Fail<T>(int code, string message) 50 { 51 return new Result<T>() { Code = code, Message = message }; 52 } 53 54 public static FailResult Fail(int code, string message) 55 { 56 return new FailResult() { Code = code, Message = message }; 57 } 58 } 59 60 public class FailResult : Result 61 { 62 } 63 64 public class User 65 { 66 } 67 }