I've faced myself in a situation, when my overridden ToString()
method would use one of the instance's collections.
public override string ToString()
{
string returnStr = "testString";
lock (_sync)
{
returnStr = $"{returnStr}: {string.Join(",", _testList)}"; // where _testList is a List<string> in the class's scope
}
return returnStr;
}
Since we are talking about a multi-threaded application, I was wondering, since I would have to use lock()
inside the ToString()
method's body in order to avoid the collection's modification while my return string is being generated. While I'm doing modifications on the collection, the same object (_sync
) is being locked, of course.
But, this method is being used by several other processes as well, such as the Visual Studio's Debugger and who knows what else, since this method is being inherited from the Object
class itself.
For example: I fear that it might being called more often behind the scene (by the framework or anything else), and would have to use the locking (which could lead to performance loss), or it might cause deadlock while I'm debugging in a bad moment.
Question:
Should I care about this situation, since it could cause problems, or is it OK to use object locking inside ToString()
(and in other inherited methods from .net types)?
Are there any better alternative solutions in order to achieve this same goal?
Note: I was thinking about to generate the required string from the collection every time when that is being modified (inside the lock, where it is being manipulated), so I would have the collection's string format ready to be concatenated in the ToString()
method itself. I guess it would be even better for performance, since the process of string.Join()
wouldn't have to run at every call of ToString()
, but I'm really curious to know more about this situation.
Thanks!
When you create a custom class or struct, you should override the ToString method in order to provide information about your type to client code. For information about how to use format strings and other types of custom formatting with the ToString method, see Formatting Types.
The toString() method returns a string representing the specified string value.
No, because if you want to call toString method like ClassName.
The lock statement acquires the mutual-exclusion lock for a given object, executes a statement block, and then releases the lock. While a lock is held, the thread that holds the lock can again acquire and release the lock. Any other thread is blocked from acquiring the lock and waits until the lock is released.
Do you really need/use the ToString()
that often?
Your scenario seems more of a business logic and I wouldn't mix it up with the ToString()
implementation.
I would go for something like: GetSnapshotRepresentation()
that uses locks and the whole conundrum and leave ToString()
returning something very lightweight (e.g. id, type, something immutable, etc.)
Putting locks and that heavy machinery into ToString()
you will block your writers if you make calls to ToString()
that you didn't want/needed to do.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With