系统要求方法都返回 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的更多相关文章

  1. C#中的类型转换-自定义隐式转换和显式转换

    目录 前言 基础知识 示例代码 实际应用 问题 答案 报错 用户定义的转换必须是转换成封闭类型,或者从封闭类型转换 参考 其他 应用和设计 读音 参考 前言 有时我们会遇到这么一种情况:在json数据 ...

  2. scala自定义隐式转换

    Scala自定义隐式转换 一.编写隐式转换类 /** * Author Mr. Guo * Create 2019/4/20 - 17:40 */ object StringImprovments { ...

  3. F#中的自定义隐式转换

    我们知道隐式变换在可控情况下会使代码变得简洁.熟悉C#的都知道C#中可以自定义隐式变换,例如 public class A { private int data; public static impl ...

  4. ahjesus自定义隐式转换和显示转换

    implicit    关键字用于声明隐式的用户定义类型转换运算符. 如果可以确保转换过程不会造成数据丢失,则可使用该关键字在用户定义类型和其他类型之间进行隐式转换. 参考戳此 explicit    ...

  5. 大数据技术之_16_Scala学习_06_面向对象编程-高级+隐式转换和隐式值

    第八章 面向对象编程-高级8.1 静态属性和静态方法8.1.1 静态属性-提出问题8.1.2 基本介绍8.1.3 伴生对象的快速入门8.1.4 伴生对象的小结8.1.5 最佳实践-使用伴生对象解决小孩 ...

  6. 9. Scala隐式转换和隐式值

    9.1 隐式转换 9.1.1 提出问题 先看一个案例演示,引出隐式转换的实际需要=>指定某些数据类型的相互转化 object boke_demo01 { def main(args: Array ...

  7. C#中的隐式转换

    你是否考虑过这个问题:为什么不同类型之间的变量可以赋值,而不需要强制转换类型?如: int i = 1; long l = i; object obj = 1; Exception exception ...

  8. 无废话Android之smartimageview使用、android多线程下载、显式意图激活另外一个activity,检查网络是否可用定位到网络的位置、隐式意图激活另外一个activity、隐式意图的配置,自定义隐式意图、在不同activity之间数据传递(5)

    1.smartimageview使用 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&q ...

  9. 深入理解Scala的隐式转换系统

    摘要: 通过隐式转换,程序员可以在编写Scala程序时故意漏掉一些信息,让编译器去尝试在编译期间自动推导出这些信息来,这种特性可以极大的减少代码量,忽略那些冗长,过于细节的代码.   使用方式: 1. ...

随机推荐

  1. printf 输出前导0

    printf ("%3d\n", 5); printf ("%03d\n", 5); 输出为

  2. 一、shell编程与变量

    目录 命令是什么 命令是如何运行的: 基本语法 解释器 注释 如何执行 输入.输出流 重定向 管道符 | 变量 常见Shell变量的类型包括: 变量命名原则 单引号和双引号 反引号 变量作用范围 查看 ...

  3. Boogie's First Blog

    这是boogie在博客园的第一篇随笔,祝大家身体健康,心情愉悦.

  4. 『忘了再学』Shell流程控制 — 35、多分支case条件语句

    目录 1.case条件语句介绍 2.case语句需要注意的内容 3.练习 示例1 示例2 1.case条件语句介绍 case语句和if-elif-else语句一样都是多分支条件语句,不过和if多分支条 ...

  5. wcf .net webService和 .net webApi的联系与差异

    首先,我们需要清楚它们的概念,然后才能走好下一步. wcf是对于ASMX,.Net Remoting,Enterprise Service,WSE,MSMQ等技术的整合,它是一种重量级消息交互框架,广 ...

  6. Maven-打包jar指定main函数所在类的一个例子

    问题描述:maven打包jar时,由于带main方法的类没有被加入manifest中,导致执行java -jar mvn-jar-1.0-SNAPSHOT.jar时,会提示没有主清单属性. 解决办法: ...

  7. SLF4J 日志门面

    目录 01.简单介绍 02.日志级别 03.入门案例 03.动态打印 04.异常打印 05.日志集成 06.集成 logback 07.集成 slf4j-nop 08.集成 log4j 09.集成 j ...

  8. 动态树 — Link_Cut_Tree

    [模板]动态树(Link Cut Tree) Link-cut-tree是一种维护动态森林的数据结构,在需要动态加边/删边的时候就需要LCT来维护. Link-cut-tree的核心是轻重链划分,每条 ...

  9. Docker — 从入门到实践PDF下载(可复制版)

    0.9-rc2(2017-12-09)修订说明:本书内容将基于DockerCEv17.MM进行重新修订,计划2017年底发布0.9.0版本.旧版本(Docker1.13-)内容,请阅读docker-l ...

  10. vue封装原生的可预览裁剪上传图片插件H5,PC端都可以使用

    思路:1.先做出一个上传的图片的上传区 <!-- 上传区 --> <label for="fileUp"> <div class="upBo ...