You don't need to make multiple calls to string.Replace() - it replaces all occurences in a single pass. See the MSDN documentation. You only need to make multiple calls if you are replacing different input sequences within the string (which may be what you're implying in your question).
In that case, I would use string.Split and string.Join for this:
var replaced = string.Join( "_", input.Split( new[]{'x','y','z'} ) );
This will split the string at every location where one of the characters 'x', 'y', or 'z' occurs (replace with your set) and will rejoin the fragments using the '_' character -- effectively replacing the originals. This approach is NOT necessarily more efficient than multiple calls to string.Replace - that would depend on the length of the input string, the number of occurences of the characters to replace, and so on. You would need to do profiling with real-world data to determine what is faster. What this approach does do, however, is make the code more concise.
As far as performance is concerned - I would go with the simplest and most readable solution first, and if testing demonstrates a problem - then I would profile and decide what alternative solutions to pursue (if any). Unless there are strong reasons to do otherwise, my personal priorities when writing code are:
- Make it correct.
- Make it clear.
- Make it concise.
- Make it fast.
- .. In that order.