使用自定义隐式转换快速创建失败Result
系统要求方法都返回 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, "用户不存在");
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 : Result<object>
6 {
7 // 新增加的方法
8 public static FailResult Fail(int code, string message)
9 {
10 return new FailResult() { Code = code, Message = message };
11 }
12 }
这样的话,不论时成功还是失败,我们都不需要指定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 }
使用自定义隐式转换快速创建失败Result的更多相关文章
- C#中的类型转换-自定义隐式转换和显式转换
目录 前言 基础知识 示例代码 实际应用 问题 答案 报错 用户定义的转换必须是转换成封闭类型,或者从封闭类型转换 参考 其他 应用和设计 读音 参考 前言 有时我们会遇到这么一种情况:在json数据 ...
- scala自定义隐式转换
Scala自定义隐式转换 一.编写隐式转换类 /** * Author Mr. Guo * Create 2019/4/20 - 17:40 */ object StringImprovments { ...
- F#中的自定义隐式转换
我们知道隐式变换在可控情况下会使代码变得简洁.熟悉C#的都知道C#中可以自定义隐式变换,例如 public class A { private int data; public static impl ...
- ahjesus自定义隐式转换和显示转换
implicit 关键字用于声明隐式的用户定义类型转换运算符. 如果可以确保转换过程不会造成数据丢失,则可使用该关键字在用户定义类型和其他类型之间进行隐式转换. 参考戳此 explicit ...
- 大数据技术之_16_Scala学习_06_面向对象编程-高级+隐式转换和隐式值
第八章 面向对象编程-高级8.1 静态属性和静态方法8.1.1 静态属性-提出问题8.1.2 基本介绍8.1.3 伴生对象的快速入门8.1.4 伴生对象的小结8.1.5 最佳实践-使用伴生对象解决小孩 ...
- 9. Scala隐式转换和隐式值
9.1 隐式转换 9.1.1 提出问题 先看一个案例演示,引出隐式转换的实际需要=>指定某些数据类型的相互转化 object boke_demo01 { def main(args: Array ...
- C#中的隐式转换
你是否考虑过这个问题:为什么不同类型之间的变量可以赋值,而不需要强制转换类型?如: int i = 1; long l = i; object obj = 1; Exception exception ...
- 无废话Android之smartimageview使用、android多线程下载、显式意图激活另外一个activity,检查网络是否可用定位到网络的位置、隐式意图激活另外一个activity、隐式意图的配置,自定义隐式意图、在不同activity之间数据传递(5)
1.smartimageview使用 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&q ...
- 深入理解Scala的隐式转换系统
摘要: 通过隐式转换,程序员可以在编写Scala程序时故意漏掉一些信息,让编译器去尝试在编译期间自动推导出这些信息来,这种特性可以极大的减少代码量,忽略那些冗长,过于细节的代码. 使用方式: 1. ...
随机推荐
- JAVA - 线程同步和线程调度的相关方法
JAVA - 线程同步和线程调度的相关方法 wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁:wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等 ...
- Jmeter跨线程组获取token(彻底解决因格式token报错)
将token设置为全局变量网上方式方法千千万,但是你就是获取token会失败,不是提示格式错误,就是提示无法获取token,没安装Jmeter的可以查看前两期教程,有详细介绍 在工作当中如果仅仅是一个 ...
- 掘地三尺搞定 Redis 与 MySQL 数据一致性问题
Redis 拥有高性能的数据读写功能,被我们广泛用在缓存场景,一是能提高业务系统的性能,二是为数据库抵挡了高并发的流量请求,点我 -> 解密 Redis 为什么这么快的秘密. 把 Redis 作 ...
- <%= %> <%- %> <% %>是什么意思?
.ejs文件后缀的数据渲染,这是服务器端的.把 .html改成 .ejs, (1)<%= %>相当于html中的innerTEXT,导出不包含标签 . (2)<%- %>相当于 ...
- UiPath循环活动Do While的介绍和使用
一.Do While的介绍 先执行循环体, 再判断条件是否满足, 如果满足, 则再次执行循环体, 直到判断条件不满足, 则跳出循环 二.Do While在UiPath中的使用 1. 打开设计器,在设计 ...
- java: 程序包org.springframework.boot不存在
如果你的settings中的maven配置没问题的话,尝试下面这个 在控制台输入 mvn idea:idea 重构一下
- python测试开发django-197.django-celery-beat 定时任务
前言 django-celery-beat 可以支持定时任务,把定时任务写到数据库. 接着前面这篇写python测试开发django-196.python3.8+django2+celery5.2.7 ...
- 4-1 Spring框架基础知识
Spring框架基础知识 1.Spring 框架作用 主要解决了创建对象和管理对象的问题. 自动装配机制 2.Spring 框架 (Spring容器,JavaBean容器,Bean容器,Spring容 ...
- shell查询prometheus数据
#shell查询prometheus数据 shell使用curl调用HTTP API执行PromQL /api/v1/query查询某一时刻的数据 查询条件PromSQL复杂时, 传入接口/api/v ...
- SP8496 NOSQ - No Squares Numbers 题解
To SP8496 这道题可以用到前缀和思想,先预处理出所有的结果,然后 \(O(1)\) 查询即可. 注意: 是不能被 \(x^2(x≠1)\) 的数整除的数叫做无平方数. \(d\) 可以为 \( ...