views:

945

answers:

4

We have taken over some .NET 1.1 Windows Service code that spawns threads to read messages off a queue (SeeBeyond eGate JMS queue, but that is not important) and in turn spawns threads to process the message in the target application service. We are continually encountering logic and design decisions that is puzzling us to no end. Here is one example, where the message (lsMessage) has been retrieved from the queue and ready for processing

if(lsMessage != null)
{
    // Initialize a new thread class instance, pass in message
    WorkerThread worker = new WorkerThread(lsMessage);

Process:
    // Start a new thread to process the message
    Thread targetWorker = new Thread(new ThreadStart(worker.ProcessMessage));
    if(targetWorker != null)
    {
     targetWorker.Priority = ThreadPriority.Highest;
        targetWorker.Name = "Worker " + queueKey.ToString();
     targetWorker.Start();

     // wait for worker thread to join back in specified period
     bool isFinished = targetWorker.Join(SYNC_THREAD_TIMEOUT);

     string message = worker.replyMsg;

     if ( !isFinished ) // BF is timeout
     {
      targetWorker.Abort();

      // [obscure developer name] 25/10/2004: calling Join() to wait for thread to terminate.
      // for EAI listener threads problem, ensure no new thread is started 
      // before the old one ends
      targetWorker.Join();

      // prepare reply message
      string errorMsg = string.Format("EAIMsg {0}: BF is timeout. Send sync message back to caller.", worker.messageKey);
      log.Debug(errorMsg);

      message = worker.GenErrorCode(message, errorMsg);
     }

     // Commit message
     MQ.ReceiverCommit(queueKey, worker.messageKey, false);

     // Send back the response to the caller
     MQ.RespondSend(queueKey, message); 
    } 
    else 
    {
     log.Debug(string.Format("Fail to start worker thread to process sync message. Thread returned is null. Sleep for {0} milliseconds.", LIMIT_RESOURCE_SLEEP));
     Thread.Sleep(LIMIT_RESOURCE_SLEEP);
     goto Process;
    }
}

Please ignore the use of label and goto for the moment; that is not the question. Our bewilderment is the check whether the Thread object is null right after instantiation. The else statement below seems to suggest the previous developers have encountered situations like this before. Of course, the original developers are long gone. So we would like to know, can the CLR really instantiate an object after the call to the constructor and return a null? We have no knowledge of such a possibility.

+6  A: 

No, you can't get null from a class constructor (Thread is a class). The only case I know of where a constructor can (seem to) return null is Nullable<T> - i.e.

object foo = new int?(); // this is null

This is a slightly bigger problem with generics:

static void Oops<T>() where T : new() {
    T t = new T();
    if (t == null) throw new InvalidOperationException();
}

static void Main() {
    Oops<int?>();
}

(of course, there are ways of checking/handling that scenario, such as : class)

Other than that, a constructor will always either return an object (or initialize a struct), or throw an exception.

Marc Gravell
We not using nullables here of course; .NET 1.1
icelava
True enough - but I thought it was worth mentioning as an edge-case ;-p
Marc Gravell
And it's *almost* always a reference to a newly created object, too. The only exception to that that I know of is a string corner case.
Jon Skeet
+9  A: 

In my opinion, the else statement suggests that the previous developers didn't know their C#. A constructor always returns a constructed object or throws an exception.

In the very old times, C++ constructors could return null, so maybe the problem comes from that. This is no longer true in C++ either, at least for the default new operator.

Gorpik
That may be a possibility; the original developers may have some C++ background. I have seen C++ programmers habitually trying to do "funny" stuff in .NET....
icelava
+2  A: 

NO! that null check is redundant. Lot of C++ devs who moved to C# have this habit of a null check and I guess it is the same here.

The only thing is you should check the documentation to see if the constructor can throw any exception. In your case refer to http://msdn.microsoft.com/en-us/library/xx3ezzs2.aspx and as mentioned the constructor will always return a valid obj.

Sesh
That seems to be the general suspicion - C++ habits...
icelava
A: 

You can make it appear like an object ctor returns null:

http://seattlesoftware.wordpress.com/2008/03/05/returning-null-from-a-class-constructor/

Search for "Another pattern which I haven’t seen used allows an invalid object to emulate a null reference" and read from there.

Chris