C# Tip: How to temporarily change the CurrentCulture
What can you do if you need to temporarily change the CurrentCulture in C#?
It may happen, even just for testing some functionalities, that you want to change the Culture of the thread your application is running on.
The current Culture is defined in this global property: Thread.CurrentThread.CurrentCulture
. How can we temporarily change it?
An idea is to create a class that implements the IDisposable
interface to create a section, delimited by a using
block, with the new Culture:
public class TemporaryThreadCulture : IDisposable
{
CultureInfo _oldCulture;
public TemporaryThreadCulture(CultureInfo newCulture)
{
_oldCulture = CultureInfo.CurrentCulture;
Thread.CurrentThread.CurrentCulture = newCulture;
}
public void Dispose()
{
Thread.CurrentThread.CurrentCulture = _oldCulture;
}
}
In the constructor, we store the current Culture in a private field. Then, when we call the Dispose
method (which is implicitly called when closing the using
block), we use that value to restore the original Culture.
How to use it
How can we try it? An example is by checking the currency symbol.
Thread.CurrentThread.CurrentCulture = new CultureInfo("ja-jp");
Console.WriteLine(Thread.CurrentThread.CurrentCulture.NumberFormat.CurrencySymbol); //¥
using (new TemporaryThreadCulture(new CultureInfo("it-it")))
{
Console.WriteLine(Thread.CurrentThread.CurrentCulture.NumberFormat.CurrencySymbol);//€
}
Console.WriteLine(Thread.CurrentThread.CurrentCulture.NumberFormat.CurrencySymbol); //¥
We start by setting the Culture of the current thread to Japanese so that the Currency symbol is ¥. Then, we temporarily move to the Italian culture, and we print the Euro symbol. Finally, when we move outside the using
block, we get back to ¥.
Here's a test that demonstrates the usage:
[Fact]
void TestChangeOfCurrency()
{
using (new TemporaryThreadCulture(new CultureInfo("it-it")))
{
var euro = CultureInfo.CurrentCulture.NumberFormat.CurrencySymbol;
Assert.Equal(euro, "€");
using (new TemporaryThreadCulture(new CultureInfo("en-us")))
{
var dollar = CultureInfo.CurrentCulture.NumberFormat.CurrencySymbol;
Assert.NotEqual(euro, dollar);
}
Assert.Equal(euro, "€");
}
}
Conclusion
Using a class that implements IDisposable
is a good way to create a temporary environment with different characteristics than the main environment.
I use this approach a lot when I want to experiment with different cultures to understand how the code behaves when I'm not using English (or, more generically, Western) culture.
Do you have any other approaches for reaching the same goal? If so, feel free to share them in the comments section!
Happy coding!
🐧