Doing this instead of working with exceptions the usual way (
throwandcatch) is a big code smell. I think I would need a really good justification for this and I'm not sure slightly improved logging is that. I would try looking more into other possibilities, like filteringExceptions based on their type, or something like that.This code comes close to reinventing the
Exceptionmonad. You might want to study that for some ideas.Your type should protect its invariants. If it's supposed to contain a value or an exception, but not both, you shouldn't allow the user to use the type the wrong way.
A similar principle also applies to reading: if a value is not present, Value should throw an exception, instead of silently returning the default value. The same probably applies to Exception.
For a simple type like this, it often makes sense to make it immutable. Also, mutable value types are evilmutable value types are evil, you should never use them without a really good reason (and I don't see that reason here).
You should be very careful with implicit conversions. An implicit conversion should never lead to loss of information and it should be always valid. In your case, that's not true for the case when
Exceptablecontains an exception, because then the implicit conversion silently returns the default value.
So, if you want to have a conversion from Exceptable<T> to T, it should be explicit and it should throw when an exception is present.
You're checking
Valueagainstnull. This is a bad idea for several reasons:In some cases,
nullcan be a legitimate return value that does not indicate an error. Your type won't handle that correctly.If
Tis a non-nullable value type, then the default value is notnull, soHasValuewon't work correctly. If your type is meant to support only reference types, you should make that explicit by adding the constraintwhere T : classto it.The name “exceptable” is not great. Though I'm not sure what would be a better name.