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#?