This has been around since the early days of .Net - e.g., TryParse(string)
. In that particular case, it was, among other things, a way for the dev to indicate that an exception shouldn't be thrown. Internally, Parse interrupts normal execution flow by throwing an exception and incurs a performance hit, TryParse does not. This doesn't really matter if there's only an occasional Parse call, but if you're calling such a method a lot of times in a tight loop, you'll feel it.
For null checks, try-get-value is more of a band-aid, though - as it is a null check in (an unconvincing) disguise. It serves its band-aid purpose better if the API is in your control and you make it the only way to access the value, but this might be cumbersome, especially if the system is not designed in a "tell don't ask" manner.
It's better if you can make the return type non-nullable, or if you can leverage the null-object pattern (the simplest example of that is returning an empty list instead of null), or if you can leverage the Maybe/Option monad, or even if you focus your null checks on entry points, and write internal code as self-contained classes/functions that assume that the value they get is not null, even though it technically could be (except in cases where it's vital to check). The last one is helped by the presence of tests - which serve to increase your confidence that exceptions are thrown (or that there's some other potentially more appropriate form of handling) at all points where an invalid value can enter your system, and that the system beyond that is well-behaved.
P.S.
What you should be after regarding null handling is not merely to force your future self and other developers to perform null checks to avoid errors. This is a low bar. What you want is to take a more thought out approach to your error handling - you don't want your code to just be littered with checks and log calls. You want to be more deliberate about it. This lets you decluter your domain logic and write code that communicates better what is it that it's actually trying to do. It's not about hiding errors or pushing them under the rug, it's about being able to write more clearly - and if you can do that, then you're in a better possition to check if your overall logic is actually correct.
TryGetValue
is not a new method at all. And yes, I'm for using the "Try Do Thing, Out Param" pattern in all places where it makes sense and saves onnull
checks. Don't look atnull
as your "enemy", instead validate all data the moment it enters the application and not later, use nullable reference types, life will be better. :)null
in the first place and may just hide bugs. They really should have included non-nullability from the beginning, but I guess it's easy to say that now.