I am looking for a way to explain that it's unreasonable to sprinkle high-level business logic with calls to ReferenceEquals().
Here's a code snippet that I have a problem with (precondition in a method, designed to throw if we're on a wrong thread):
if (!object.ReferenceEquals(Thread.CurrentThread, RequestHandlerThread))
Is it reliable to write this instead:
if (Thread.CurrentThread != RequestHandlerThread)
I suggested to use ManagedThreadIds in the comparison based on what I commonly see in tutorials. Adversary says that comparison for reference equality seems more object-oriented.
Here's (roughly) what I saw in Reflector's view of System.Object with .NET 4.0. Keep in mind that Thread class is sealed, and has no overload for operator==.
public static bool ReferenceEquals(object objA, object objB)
{
return (objA == objB);
}
public static bool Equals(object objA, object objB)
{
return (objA == objB ||
(objA != null && objB != null && objA.Equals(objB)));
}
Here are some basic tests, verifying operation on thread pool... Did I miss any significant tests?
using System.Threading;
using System.Diagnostics;
using System.Threading.Tasks;
namespace ConsoleApplicationX
{
class Program
{
static readonly Thread mainThread;
static Program()
{
mainThread = Thread.CurrentThread;
}
static void Main(string[] args)
{
Thread thread = Thread.CurrentThread;
if (thread != Thread.CurrentThread)
Debug.Fail("");
if(Thread.CurrentThread != thread)
Debug.Fail("");
if (thread != mainThread)
Debug.Fail("");
var task = Task.Factory.StartNew(() => RunOnBackground(thread));
task.Wait();
var anotherThread = new Thread(new ParameterizedThreadStart(RunInAnotherThread));
anotherThread.Start(thread);
}
static void RunOnBackground(Thread fromInitial)
{
if (Thread.CurrentThread == fromInitial)
Debug.Fail("");
if (fromInitial != mainThread)
Debug.Fail("");
}
static void RunInAnotherThread(object fromInitialAsObject)
{
var fromInitial = (Thread)fromInitialAsObject;
if (Thread.CurrentThread == fromInitial)
Debug.Fail("");
if (fromInitial != mainThread)
Debug.Fail("");
}
}
}
Trying not to preach, but ... In general, if there is an identity property to use, in this case
Thread.ManagedThreadId
it should be used for equality comparisons unless there is a performance constraint for the executing code. The semantics of a pointer comparison are a lot different than equality. Also, the pointer comparison is dependent upon the implementation of Thread in mscorlib.
You are correct. As your reflection inquiry shows, the two ways are equivalent (barring an extra method call in the adversary's way)
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