As always, premature optimization is the root of all evil. It's also unclear from your question why you wouldn't simply use the [Conditional("DEBUG")] attribute -- if you want to remove logs in release builds, this is the way to go, period.
(Update) From .NET 4.6 onward, you can specify the parameter as FormattableString, as mentioned in the comments below your question:
void Assert(bool condition, FormattableString message)
{
if (condition)
DoSomething(message.ToString());
}
// this will actually create an instance of FormattableString
// under the hood, which will not be formatted until you
// call FormattableString.ToString() inside the method
Assert(value1 > value2, $"{value1} was not greater than {value2}");
If the condition is really rarely fulfilled, and you want to avoid creating the FormattableString instance too, and you are willing to go yet another crazy step forward, you could create a whole bunch of generic methods similar to:
void Assert<T1>(bool condition, string format, T1 a);
void Assert<T1, T2>(bool condition, string format, T1 a, T2 b);
void Assert<T1, T2, T3>(bool condition, string format, T1 a, T2 b, T3 c);
...
// if value1 is `int`, and value2 is `double`, this will resolve
// into Assert<int, double>(bool, string, int, double) -- all parameters
// are simply passed into the method, and nothing is instantiated
Assert(value1 > value2, "{0} was not greater than {1}", value1, value2);
Since these will get compiled into methods accepting actual, strongly typed parameters, there won't be any additional heap instantiations this way, so you have practically no performance burden if the condition is not fulfilled.
A quick benchmark shows that the first change (using FormattableString instead of string) is ~1.6x faster when condition is fulfilled 50% of the time (random.NextDouble() > 0.5). The approach with generic methods is ~2x faster this way:
- 5,000,000 iterations with logging in 50% cases:
- string interpolation: 5 s
FormattableString: 3 s
- generic methods: 2.5 s
If the condition is fulfilled rarely (5% of the time), first optimization resulted in ~8x speedup, while the generic approach was ~14x faster, with far less allocations:
- 5,000,000 iterations with logging in 5% cases:
- string interpolation: 3.5 s
FormattableString: 0.5 s
- generic methods: 0.25 s