当前位置:网站首页>d实验新异常
d实验新异常
2022-08-02 22:42:00 【fqbqrr】
原文
串不好,应用
变量.很容易
创建新类型.如std.algorithm
中管道一样,隐式实例化模板的返回值
.
我构建了arsd.exception
模块,新异常
重点是改进enforce
.
用法
import exception2;
enum MyError;
enum OtherError;
void main() {
int a;
try {
throw Exception2!MyError(a, "更多信息");
} catch(Exception2!(OtherError) e) {
// 不会抓它,因为它是另一个错误
import std.stdio;writeln("wrong");
} catch(Exception2!(MyError, int) e) {
// 会抓!
import std.stdio;writeln("CAUGHT!");
writeln(e);
}
}
我抛了整/串
,但只抓了整
.想法细节只是进一步
特化,可根据是否感兴趣
来处理它们.如果不关心附加数据
,可只catch(Exception2!MyError)
.
或静态列举MyError
构中数据
,而不是用MyError
来枚举.另一方面,可丢弃所有命名空间类型
的区分,而只使用Exception2!("somestring",data)
.
import exception2;
void main() {
int a;
try {
//串错误类型而不是命名空间的D类型仍可附加信息
throw Exception2!"foo bar"(a);
} catch(Exception2!"foo bar") {
//按串抓
import std.stdio;
writeln("caught");
}
}
我不大喜欢,串
不能区分不同库
.而使用enum
,可通过模块导入和命名空间
规则区分.
优点是可不提前
声明,可在抛点
声明,并在抓
点确认.我不大喜欢这种风格,但与throw new Exception("一些串")
一样方便,且可附加数据.
你可能反驳说,声明新类,并用mixin template
.声明结构
,枚举
,并在那里
声明相关数据
.好处不大.
我要说,枚
声明,得到了异常族的静态列表
,然后根据需要添加
数据.
考虑InvalidValue
族,附加信息,给了int valueGiven, int maxValue
,或int valueGiven, int minValue, int maxValue
,或string valueGiven, string expectedPattern
.一个族,可合理地附加
不同值
.
这,也是为何需要
结构化数据.
如果得到两个int
值,哪个是valueGiven
,哪个是maxValue
?还是给出了两个值
(如矩阵坐标
)?
用该机制,你可
throw Exception2!InvalidValue(MyStruct(structured, information, here);
别人可
catch(Exception2!InvalidValue)
//或
catch(Exception2!(InvalidValue, MyStruct))
来抓族或细节.
仍然工作,只是参数,
struct MyStruct {
}
//从上面,变成下面.
class InvalidValueExceptionWithMyStruct : InvalidValueException {
MyStruct data; mixin ExceptionCtor;s }
当前,异常
的信息不足.
我想用IFTI
:隐式函数模板实例化,来附加
数据,即要创建
新子类.它不能用普通
的构造函数.但可用opCall
.
此外,我还想确保派生类
可在声明点
外命名,这样你可轻松抓异常
.这排除
了匿名类,但仍可用opCall
.
深入代码
module exception2;
/+
它使用长格式模板编写,因为我想单独定义父
这样更容易.
+/
template Exception2(alias Type, T...) {
//每条添加数据都是更一般情况的特化
//这是通过父类不变,但切掉了一块来实现
//或作为所有`Exception2`的通用父级,并回退到`Exception`
static if(T.length)
alias Parent = Exception2!(Type, T[0 .. $-1]);
else
alias Parent = Exception;
class Exception2 : Parent {
//应该以不同的方式命名,或至少是`const`之类的
//但它保存在抛点传递的数据
T t;
//这是抛的主要入口点,注意它如何像`标库`中工厂模式一样,取参数并转发给新类
//在`Phobos`中用于构造,如,来自`map()`的`MapResult.`
//如果你直接使用`newException2`,必须指定所有要传递类型,但通过`opCall`,可隐式推导`R`.
//注意推导的返回值是传递过来的完整静态类型.
static opCall(R...)(R r, string file = __FILE__, size_t line = __LINE__) {
return new Exception2!(Type, T, R)(r, "", file, line); //串可包含任意
}
//你不能直接调用它!我甚至使它为`保护`
this(T t, string msg, string file = __FILE__, size_t line = __LINE__) {
this.t = t;
static if(is(Parent == Exception))
super(msg, file, line);
else
super(t[0 .. $-1], msg, file, line);
}
//这与旧的arsd.exception`基本相同
override void toString(scope void delegate(in char[]) sink) const {
import std.conv;
sink(typeid(this).name); //待办,同名长串.
sink("@");
sink(file);
sink(":");
sink(to!string(line));
sink("\n");
sink("玩笑");
//这部分是真实的:打印时,循环访问附加的数据并显示出来
foreach(idx, item; t) {
sink("\n");
sink(typeof((cast() this).t[idx]).stringof);
sink(" = ");
sink(to!string(item));
}
if(info) {
try {
sink("\n----------------");
foreach (t; info) {
sink("\n"); sink(t);
}
}
catch (Throwable) {
// 忽略更多错误.
}
}
}
}
}
这是灵活的类,它允许你定义catch(Exception2!X)
和throw Exception2!X(data)
,声明了返回为你构造
的更子类
的对象的opCall
.不是常见的静态opCall
,是我以前的旧模式
,并且它工作得很好.
我很满意.可方便地使用具更多结构
的throw new Exception("stuff")
.
边栏推荐
猜你喜欢
随机推荐
centos7安装mysql5.7步骤(图解版)
MySQL删除数据后,释放磁盘空间
脂溶性胆固醇-聚乙二醇-叠氮,Cholesterol-PEG-Azide,CLS-PEG-N3
Week 7 CNN Architectures - LeNet-5、AlexNet、VGGNet、GoogLeNet、ResNet
非关系型数据库MongoDB简介和部署
函数:计算组合数
最近公共祖先(LCA)学习笔记 | P3379 【模板】最近公共祖先(LCA)题解
In-depth study TypeScript TypeScript 】 【 class (under)
IDEA 重复代码的黄色波浪线取消设置
最新真实软件测试面试题分享,收藏了还怕进入不了大厂?
# DWD层及DIM层构建## ,220801 ,
CentOS7 安装MySQL 图文详细教程
mysql查询表中重复记录
精心整理16条MySQL使用规范,减少80%问题,推荐分享给团队
Kubernetes 进阶训练营 网络
谷粒商城-day14-商城业务与压力测试
用了 TCP 协议,数据一定不会丢吗?
采用QT进行OpenGL开发(三)着色器编程
MDL 内存描述符链表
学习基因富集工具DAVID(2)