I have a class Hopefully<T>
that contains either an error
or a value
. Whenever a method returns one of these I need to check for errors and either handle them right there, or propagate further up the call-chain:
class Hopefully<T>
{
MyError Error;
T SomeTValue;
// Implicit conversion should be defined here from Error and from T
}
public Hopefuly<int> SquareRoot(int x)
{
return x >= 0 ? sqrt(x) : new MyError(...);
}
public Hopefull<string> PrettySquareRoot(int x)
{
var r = SquareRoot(x); // r is Hopefully<int>
if (r.IsError)
return r.Error; // r.Error is MyError
var v = r.SomeTValue; // v is int
return $"the root is {v}";
}
I find this too verbose, and would like to write like this:
public Hopefull<string> PrettySquareRoot(int x)
{
var v = assume SquareRoot(x);
// v is int; if callee returned error it's escalated automatically before v is assigned
return $"the root if {v}";
}
Here the new assume
keyword would check the right-side, and if it's an error it would immediately return from the method with that error. If there is no error, it would extract SomeTValue
and assign it to v
.
So it's similar to await
in appearance, and similar to exceptions
in behavior.
Compared to exception this would have better performance on millions of errors (yes, I need every one of those errors). It's also more explicit - a programmer can silently ignore exceptions but cannot do that to Hopefully<T>
- they have to unpack the value
.
The nearest I have found so far is this [1] but this seems a lot, and there is no information on how to integrate this into Visual Studio. I would like to hear other ideas before I dive into it.
[1] Is there a way to implement custom language features in C#?