When you're writing a virtual patch you know exactly what data you're dealing with and you can allow through only what's known to be good. Any other approaches (e.g., generic rules) deal with text in bulk and are prone to false positives.
Even with this narrower focus, it's still a difficult problem. Here's a paper I wrote on this subject a while ago: https://blog.qualys.com/wp-content/uploads/2012/07/Protocol-...
Source: I am the original author of ModSecurity (but not of any of the rules packages).
For my context, I’m coming from a place of adding it to very new deployments, where the needs are constantly changing, which is why it feels a bit square-peg-round-hole I think.
I think ideally you'd want to use the rules to create some kind of temporal risk score for a given IP / client. Eg, if a single IP hits your service several times in 5 minutes with suspicious requests, then you block the request. But this isn't possible so you basically have to ensure all your rules are only looking for the most obvious and suspicious requests, otherwise you're going to get far too many false positives.
The only argument I could make in favour of using it is a lot of attacks these days are automated and therefore are quite naive because they're simply poking around for holes.