Reading — step 1 of 5
Learn
~1 min readStructs vs Classes and Errors
D uses Java-style exceptions. All exceptions extend Throwable (split into Exception for recoverable and Error for unrecoverable).
import std.stdio, std.conv;
int parsePort(string s) {
int n = to!int(s); // throws ConvException on failure
if (n < 1 || n > 65535)
throw new Exception("port out of range");
return n;
}
void main() {
try {
int p = parsePort("abc");
} catch (Exception e) {
writeln("failed: ", e.msg);
} finally {
// cleanup
}
}
Custom exceptions — extend Exception:
class NotFoundException : Exception {
string id;
this(string id) {
super("not found: " ~ id);
this.id = id;
}
}
Contracts — D's design-by-contract built in:
int divide(int a, int b)
in { assert(b != 0, "divisor must be nonzero"); }
out (result) { assert(result * b + a % b == a); }
do {
return a / b;
}
in— preconditions, checked on entryout— postconditions, checked on return (with the result)do— body (used to bebody, now reserved)
Contracts are runtime assertions by default but the compiler can elide them in release builds. Useful for catching bugs during development.
scope statements — guaranteed cleanup:
void open() {
auto file = openFile();
scope (exit) file.close(); // always runs
scope (success) commitTransaction(); // only on normal return
scope (failure) rollback(); // only on exception
// ... use file ...
}
Cleaner than try/finally for resource management.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…