Both int
and string
as parameters in this method are effectively immutable and cannot be changed by outside code.
So there is no need to care about thread-safety with either Format method or String.Concat in this case.
But let us assume that we have some class MyObject that is mutable and can be changed from outside:
public class MyClass
{
public Int32 value1 { get; set; }
public String value2 { get; set;}
}
public static string WriteResult2(MyObject obj)
{
return "Result: value=" + obj.value1 + " name=" + obj.value2 ;
}
In this case whether with first approach or second you can return inconsistent value (it both value1 and value2 are changed after one value is already put to output.)
As @JonSkeet pointed it is not actually the method itself that is unsafe, but the class itself is unsafe to be shared in such manner between different threads.
To handle this situation you will have to either create special thread-safe instance method:
public class MyClass
{
private Object lockObj = new Object();
public Int32 value1
{
get
{
lock (this.lockObj) { ... });
}
set
{
lock (this.lockObj) { ... });
}
}
public String value2
{
get
{
lock (this.lockObj) { ... });
}
set
{
lock (this.lockObj) { ... });
}
}
public string WriteResult2()
{
lock (this.lockObj)
{
return "Result: value=" + this.value1 + " name=" + this.value2 ;
}
}
}
Or use some additional locking over such instances in methods that use it. The first in-class approach is obviously less error-prone, but may reduce performance and create a lot of boiler-plate code. Ideally, in concurrent programming the less you need to care about shared mutable state and its consistency the better.