我们接管了一些.NET 1.1 Windows服务代码,它生成线程以从队列中读取消息(SeeBeyond eGate JMS队列,但这并不重要),然后生成线程来处理目标应用程序服务中的消息.我们不断遇到令我们困惑的逻辑和设计决策.这是一个示例,其中已从队列中检索消息(lsMessage)并准备好进行处理
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; } }
请暂时忽略标签和goto的使用 ; 这不是问题.我们的困惑是在实例化后检查Thread对象是否为空.下面的else语句似乎表明之前的开发人员之前遇到过这样的情况.当然,原来的开发者早已不复存在.所以我们想知道,在调用构造函数并返回null之后CLR是否真的可以实例化一个对象?我们不了解这种可能性.
在我看来,该else
声明表明,以前的开发人员不知道他们的C#.构造函数始终返回构造对象或引发异常.
在过去,C++构造函数可能会返回null
,所以问题可能来自于此.这在C++中也不再适用,至少对于默认new
运算符来说是这样.
编辑:澄清有一个疯狂的边缘的情况下,你可以得到null
从类的构造函数,但坦率地说,我不认为任何真正的代码应该永远指望对付这种级别的疯狂:什么是你见过的最奇怪的角落情况C#还是.NET?.对于所有正常意图:它不会发生.
不,你不能从类构造函数中获取null (Thread
是一个类).我知道构造函数可以(似乎)返回的唯一情况null
是Nullable
- 即
object foo = new int?(); // this is null
这是泛型的一个稍大的问题:
static void Oops() where T : new() { T t = new T(); if (t == null) throw new InvalidOperationException(); } static void Main() { Oops (); }
(当然,有检查/处理该方案的方法,例如: class
)
除此之外,构造函数将始终返回一个对象(或初始化一个struct),或抛出一个异常.