string s = "ABCD\x09\x05\r\n";
var replace =
s.Select(c => Char.IsControl(c) ? ((int)c).ToString("X2") : c.ToString())
.Aggregate(new StringBuilder(), (sb, t) => sb.Append(t))
.ToString();
Извините, компилятор не удобен, но я думаю, что он компилирует и выполняет свою работу.
Кроме того, этот тип обходит строку дважды (один раз, чтобы проецировать каждый символ на шестнадцатеричную замену или строку, а затем снова для агрегирования), и вы можете избежать этого, объединив проекцию в вызов Enumerable.Aggregate
, но это более понятно, и, вероятно, это не имеет большого значения, если только это не критично для производительности.