While stepping through some code in the debugger I encountered a wonderful reminder of how nice it is to inhabit the managed world of Type Verifiable code.
There's a library of functions (library A) that gets statically linked into another library of functions (library Z). Lib Z defines type FOO (a class with several methods longer than several thousand lines of code each, but that's a rant for another day).
Unfortunately lib A also defines a type FOO. The lib A version is an earlier incarnation of lib Z's type FOO. Being an earlier version, lib A's FOO has not kept up with the times.
When a lib Z function calls a lib A function and passes it a pointer to FOO, what exactly does lib A operate on? Of course it uses its own version of FOO (you don't seriously think we're using namespaces to solve this problem do you?) which, being out of date, has all its parts in different places.
So the other developer working on this problem spends hours of frustration trying to figure out why FOO->SomeCount goes from the low 400s to the millions as soon as it enters lib A's FOO. In despair he decides its probably related to crossing a process boundary (lib A used to be dynamically linked to lib Z but is no longer) and so opts to copy the code from lib A into lib Z.
This solves the immediate problem of course since now the function is using the version of type FOO that the developer expects.
But it creates another, more subtle problem. One that will not rear its ugly head until many months, possibly years, into the future. In fact, it was exactly this sort of decision, taken many years ago in the past, that created the current problem. Why is type FOO defined in 2 separate places? This fork in the code led to the divergent types that led the misdiagnosis that lead to yet another fork in the code.
All because the compiler in the native world can't verify that the type you request matches the type you're applying it to. Anything can be cast to anything; at best the compiler can warn you. It's the slow accumulation of nuisances like this that leads to the Big Ball of Mud. Software that's so brittle it can't be modified and must eventually be rebuilt from scratch.
In the managed world this type mismatch would never have passed compilation.