Given that the .NET team has stated (I’ll find a source…) that they regret the design of the primitive type’s parsing methods (e.g. Int32.TryParse(String s, out Int32 result)) why haven’t these been updated with a more obvious and client-friendly variant?
Framework Version:
Int32? numValue;
Int32 placeHolder;
if (! Int32.TryParse("not a number", out placeHolder))
numValue = 10;
Improved Version:
var numValue = Int32.Parse("not a number", 10);
Where the signature for the improved parsing method is:
public static Int32? Parse(String s, Int32? defaultValue = null);
And it might have a naive implementation of:
public static Int32? Parse(String s, Int32? defaultValue = null) {
Int32 temp;
return ! Int32.TryParse(s, out temp)
? defaultValue
: temp;
}
I’m not sure there would be a definitive answer to this unless someone from the BCL team has a story to tell.
Some considerations might be:
existing code bases with very little (debatable if any) gain. Some
might argue that it would be a detriment for the reasons below.
box the wrappedwrap the underlying value causing a (minor) performance hitalways even when you expect your parse to succeed and don’t want a
nullable type anyway.
Parsemethod throws exceptions for the exceptional case that the input
is invalid. This is generally more performant as we don’t have extra
error handling code for when we don’t need it, and expected from a
design point of view. If you plan on handling the invalid case,
that’s what
TryParseis for.int Parse(string, int? defaultValue)andint, mostly with regards to their error handling. NoticeParse(string)
I’ve remove the optional part of the first method otherwise it would
make no sense to have both methods (you would never be able to call
your method without explicitly passing in
null). At this point, itwould be a bit confusing as one overload throws an exception on
failure whereas the other one does not. There are a few exceptions
to this, such as
Type.GetType
but they’re generally rare and in such cases they make use of an explicitly named parameter indicating that it will or will not throw an exception.
TryParseas designed is that it is prettyexplicit by way of its API for handling the pass/fail result. Rather
than a magic number/result (
null) indicating a failure, it returnsa separate true/false value. Now, some mechanisms do this
(
String.IndexOffor example returning -1) so it’s debatable ifthis is a good thing or a bad thing. Depending on your practice,
using the return
true/falsevalue might be easier, or using themagic
nullresult might be. But they decided I guess to not muddythe waters with two methods doing the exact same thing but with
slightly different signatures/return values.
Another consideration is how common nullable value types are. Are
you really using
Int32?in many places? Or is it just forerror/input handling? In my experience, nullable values are mostly
used for database I/O (and even then, not that often). The only
other times could be for input from non-trusted sources which would
only be for the initial interfacing; all underlying code would still
be typed against the non-nullable
Int32. In such case you have twomethods, the original:
Or your suggestion:
Note how similar both are. Your suggestion really provides very
little, if anything to this case. Also note the usage of
GetValueOrDefault(), this is actually the faster/better way to access the wrapped value if you know it’s non-null, but rarely (atleast from what I see on the internet) is it used over the
Valueaccessor. If the BCL added/changed the
Parsemethod as yousuggest, I think a lot of people would be unnecessarily hitting
the
Valueaccessor.I can’t comment specifically on cases using nullable values
significantly throughout an application design and/or its layers,
but in my experience they are rarely used or should be rarely used (to me, it’s a code smell almost on the level of “stringly-typed” data)
Ultimately, I believe part of the reason why extension methods were added (aside from Linq) was to allow users to roll their own API as needed. In your case, you can easily add an extension method to obtain the syntax you want:
The teams generally favour maintaining the status quo and additions have to provide a significant enough benefit to be added to the system, and the team also considers what workarounds already exist in the API as-is. I’d suggest that given the extension method option, it’s not that big of a concern to change the API considering the signficant breaking nature of it.