A better pattern used in say, F#, would be to return the tuple of <bool, T>, which could handle reference types and value types uniformly unlike Nullable. That won't slide in C# though as there's no syntactic sugar for tuples, and calling .Item1, .Item2 is too "inelegant" for the regular programmer.
For now though, the bool Try_(_, out _ _) is still the preferred method by most.
Func and Action are certainly useful, but sometimes having a named delegate type is still preferable because you can capture the purpose of the delegate in it's name, rather than resorting to doc comments nobody is going to read anyway.
I agree that it would be nice if C# checked that you dealt with the null case of the return - Resharper will happily warn me if I haven't, but it would be nice if the base compiler did. Maybe in the future!
The point is that it is not necessarily correct to conflate the nullability of the parse with the correctness of the parse. If I wanted to parse a string into a Foo, null might be a valid value for a successful parse to return, say because the rule is that the string "(null)" maps to a null Foo.
I have implemented TryParse methods on many reference types with exactly these semantics - object on success, null on failure (often with details logged at DEBUG).
Also, I'm constantly frustrated how many core libs freak the heck out over a null string vs. an empty string. Obviously there are places to distinguish those, but if I'm trying to create a nullable int out of the text that is not one of them.
public static class StringExtensions
{
public static Int32? ParseAsNullableInt32(this String self, Int32? fallback = null)
{
Int32 result;
return Int32.TryParse(self, out result) ? result : fallback;
}
}In the case of the XML Serializer, that means that if I declare a class with Nullable<int> Foo {get;set;}
and
<Foo />
appears in the XML body, then it blows up. The WebForms stuff is similarly pathetic about empty strings. There is no useful distinction between empty strings and nulls when we're talking about dates or numbers or something like that, so throwing an exception in this case is just plain wrong. It's not even protecting backwards compatibility because pre-2.0 C# didn't even have nullable ints.They've also done a terrible job of making a first class Windows UI library for .NET; WinForms was always clunky and limited in the subset of MFC/GDI it exposed; WPF was too radical and didn't make sufficient use of the underlying native capabilities of Windows - and the WinRT story has been confused from day 1.
So the
method would probably nowadays be better done as Similarly, WinForms has loads of different events of different types with individual delegates created for them. Nowadays you'd use Func and Action instead.