How about new syntactical sugar for exception checking?
-
We get a shiny new "?" operator that takes
string result = null;
if (field != null)
{
result = field.Value;
}and converts this to
string result = field?.Value
So what about the case where we're handling a flaky API
string result = null;
try
{
result = DodgyApi.GetValue(); // may throw an exception
}
catch
{
result = null;
}What would you suggest we do for that? What about a headasplode (*) operator
string result = DodgyApi.GetValue*();
where
GetValue*
will silently swallow the exception thrown byGetValue
and returndefault
. Or am I setting a new standard for lazy, shameful programming here this hot, lazy afternoon?cheers Chris Maunder
Why not make it a compiler flag that can be set once per file.
#pragma OnError ResumeNext
Did you ever see history portrayed as an old man with a wise brow and pulseless heart, waging all things in the balance of reason? Is not rather the genius of history like an eternal, imploring maiden, full of fire, with a burning heart and flaming soul, humanly warm and humanly beautiful? --Zachris Topelius Training a telescope on one’s own belly button will only reveal lint. You like that? You go right on staring at it. I prefer looking at galaxies. -- Sarah Hoyt
-
We get a shiny new "?" operator that takes
string result = null;
if (field != null)
{
result = field.Value;
}and converts this to
string result = field?.Value
So what about the case where we're handling a flaky API
string result = null;
try
{
result = DodgyApi.GetValue(); // may throw an exception
}
catch
{
result = null;
}What would you suggest we do for that? What about a headasplode (*) operator
string result = DodgyApi.GetValue*();
where
GetValue*
will silently swallow the exception thrown byGetValue
and returndefault
. Or am I setting a new standard for lazy, shameful programming here this hot, lazy afternoon?cheers Chris Maunder
Just NO!
#SupportHeForShe Government can give you nothing but what it takes from somebody else. A government big enough to give you everything you want is big enough to take everything you've got, including your freedom.-Ezra Taft Benson You must accept 1 of 2 basic premises: Either we are alone in the universe or we are not alone. Either way, the implications are staggering!-Wernher von Braun
-
We get a shiny new "?" operator that takes
string result = null;
if (field != null)
{
result = field.Value;
}and converts this to
string result = field?.Value
So what about the case where we're handling a flaky API
string result = null;
try
{
result = DodgyApi.GetValue(); // may throw an exception
}
catch
{
result = null;
}What would you suggest we do for that? What about a headasplode (*) operator
string result = DodgyApi.GetValue*();
where
GetValue*
will silently swallow the exception thrown byGetValue
and returndefault
. Or am I setting a new standard for lazy, shameful programming here this hot, lazy afternoon?cheers Chris Maunder
Chris Maunder wrote:
string result = DodgyApi.GetValue*();
What about string result = DodgyApi.GetValue*(value); as you don't always want the type default. Not sure how we define my value for reference types, maybe it could use the C# new type { prop1 = val1, ...} paradigm? Anyway, no, bad idea. I want to fire people who silently swallow exceptions. At least, the code should be logging at some level, "hey, DodgyApi failed, using default value x" so that (in theory) somebody could investigate and make the api somewhat less dodgy.
-
Why not make it a compiler flag that can be set once per file.
#pragma OnError ResumeNext
Did you ever see history portrayed as an old man with a wise brow and pulseless heart, waging all things in the balance of reason? Is not rather the genius of history like an eternal, imploring maiden, full of fire, with a burning heart and flaming soul, humanly warm and humanly beautiful? --Zachris Topelius Training a telescope on one’s own belly button will only reveal lint. You like that? You go right on staring at it. I prefer looking at galaxies. -- Sarah Hoyt
I just love to imagine the absolute mayhem such a pragma would allow.
cheers Chris Maunder
-
We get a shiny new "?" operator that takes
string result = null;
if (field != null)
{
result = field.Value;
}and converts this to
string result = field?.Value
So what about the case where we're handling a flaky API
string result = null;
try
{
result = DodgyApi.GetValue(); // may throw an exception
}
catch
{
result = null;
}What would you suggest we do for that? What about a headasplode (*) operator
string result = DodgyApi.GetValue*();
where
GetValue*
will silently swallow the exception thrown byGetValue
and returndefault
. Or am I setting a new standard for lazy, shameful programming here this hot, lazy afternoon?cheers Chris Maunder
Don't use DodgyApi directly. string result = MyDodgyApiWrapper.GetValue(); Your wrapper can log any exceptions, provide a reasonable default value "Service unavailable. Try back later.", etc. If a better backend evolves later, just update your wrapper.
-
You could always write a helper method.
string GetString(int x)
{
throw new NotImplementedException();
}void Foo()
{
string s = NoEx.Run(() => GetString(100));
Console.WriteLine(s == null);
}class NoEx
{
public static T Run<T>(Func<T> method)
{
try
{
return method();
}
catch
{
return default(T);
}
}
}Not as clean as syntactic sugar, but fairly close :-)
Regards, Nish
Website: www.voidnish.com Blog: voidnish.wordpress.com
If you make Run an extension method and rename it to IgnoreExceptions for clarity, you can say:
var s = (() => GetString(100)).IgnoreExceptions();
You can go one further and add another parameterized type for the catch's use to only ignore certain types of exceptions:
var s = (() => GetString(100)).Ignore();
-
We get a shiny new "?" operator that takes
string result = null;
if (field != null)
{
result = field.Value;
}and converts this to
string result = field?.Value
So what about the case where we're handling a flaky API
string result = null;
try
{
result = DodgyApi.GetValue(); // may throw an exception
}
catch
{
result = null;
}What would you suggest we do for that? What about a headasplode (*) operator
string result = DodgyApi.GetValue*();
where
GetValue*
will silently swallow the exception thrown byGetValue
and returndefault
. Or am I setting a new standard for lazy, shameful programming here this hot, lazy afternoon?cheers Chris Maunder
-
How about something like this:
public abstract class DodgyResult<T>
{
public abstract bool Succeeded { get; }
public abstract T Value { get; }
public abstract Exception Error { get; }public T GetValueOrDefault(T defaultValue = default(T)) { return Succeeded ? Value : defaultValue; } public static DodgyResult<T> Success(T value) { return new SuccessResult(value); } public static DodgyResult<T> Failure(Exception error) { return new ErrorResult(error); } // Explicit cast to the return type; // throws an InvalidOperationException if this is a failure result: public static explicit operator T(DodgyResult<T> result) { return result.Value; } // Allow the result to be treated as a bool value indicating success: public static bool operator true(DodgyResult<T> result) { return result.Succeeded; } public static bool operator false(DodgyResult<T> result) { return !result.Succeeded; } private sealed class SuccessResult : DodgyResult<T> { public SuccessResult(T value) { Value = value; } public override bool Succeeded => true; public override T Value { get; } public override Exception Error => null; } private sealed class ErrorResult : DodgyResult<T> { public ErrorResult(Exception error) { Debug.Assert(error != null); Error = error; } public override bool Succeeded => false; public override Exception Error { get; } public override T Value { // Wrap the error in a new exception to preserve the original stack trace: get { throw new InvalidOperationException(Error.Message, Error); } } }
}
public static class DodgyResult
{
// Helper to let the compiler infer the generic parameter:
public static DodgyResult<T> Success<T>(T value)
{
return DodgyResult<T>.Success(value);
}public static DodgyResult<T> RunDodgy<T>(Func<T> dodgyFunc) { try { return Success(dodgyFunc()); } catch (Exception ex) { return DodgyResult<T>.Failure(ex);
Excellent. Thanks for this example, Richard !
«There is a spectrum, from "clearly desirable behaviour," to "possibly dodgy behavior that still makes some sense," to "clearly undesirable behavior." We try to make the latter into warnings or, better, errors. But stuff that is in the middle category you don’t want to restrict unless there is a clear way to work around it.» Eric Lippert, May 14, 2008
-
You could always write a helper method.
string GetString(int x)
{
throw new NotImplementedException();
}void Foo()
{
string s = NoEx.Run(() => GetString(100));
Console.WriteLine(s == null);
}class NoEx
{
public static T Run<T>(Func<T> method)
{
try
{
return method();
}
catch
{
return default(T);
}
}
}Not as clean as syntactic sugar, but fairly close :-)
Regards, Nish
Website: www.voidnish.com Blog: voidnish.wordpress.com
Very interesting Nish, I was puzzled by the omission of a Type argument to NoEx.Run, and realize that my habit of always writing out the Type arguments wasn't necessary in this case. I've made a note to try and find more information on exactly when the compiler can infer the Type which renders including the Type an option. thanks !
«There is a spectrum, from "clearly desirable behaviour," to "possibly dodgy behavior that still makes some sense," to "clearly undesirable behavior." We try to make the latter into warnings or, better, errors. But stuff that is in the middle category you don’t want to restrict unless there is a clear way to work around it.» Eric Lippert, May 14, 2008
-
;)
cheers Chris Maunder
-
We get a shiny new "?" operator that takes
string result = null;
if (field != null)
{
result = field.Value;
}and converts this to
string result = field?.Value
So what about the case where we're handling a flaky API
string result = null;
try
{
result = DodgyApi.GetValue(); // may throw an exception
}
catch
{
result = null;
}What would you suggest we do for that? What about a headasplode (*) operator
string result = DodgyApi.GetValue*();
where
GetValue*
will silently swallow the exception thrown byGetValue
and returndefault
. Or am I setting a new standard for lazy, shameful programming here this hot, lazy afternoon?cheers Chris Maunder