Just came across another slightly more interesting example. We have code that has to do essentially the same thing for three different document types: it loops through a passed-in list and for each item, adds an object to a document, then initialises that object with details from the item.
The "logic" in all 3 cases is exactly the same, yet there were 3 different implementations, one for each document type. The only difference between the 3 is that the function you need to call to add the object
is different for each document type, and the library we're using (the MS DocumentFormat.OpenXml library as it happens) doesn't provide an abstraction for just calling the same function regardless of document type. In fact, creating such an abstraction wouldn't be complex at all - if you look at the decompiled MS source, they've basically implemented the same function 3 times, but using an internal function not available to us.
As it happens there was a bug in our initialisation code (missing null check!), but of course it was duplicated across all 3 functions. I basically had 3 options:
a) make the same null check fix in all 3 versions, thus resulting in 3 even longer functions with the same logic
b) collapse all 3 functions into one and provide an abstraction for the "adding object to document" part
c) refactor the 3 functions to use the same helper function just to do the object initialisation
In the end I went with c) because it required the least amount of code, and the only genuine duplication really is the foreach statement. But arguably if MS had kept their library DRY in the first place we would never have ended up with so much code duplication.