Подтвердить что ты не робот

Может ли конструктор объекта вернуть null?

Мы применили некоторый код службы .NET 1.1 Windows, который порождает потоки для чтения сообщений из очереди (SeeBeyond eGate JMS queue, но это не важно) и, в свою очередь, порождает потоки для обработки сообщения в целевой службе приложения. Мы постоянно сталкиваемся с логическими и дизайнерскими решениями, которые нас недооценивают. Вот один пример, когда сообщение (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 значение null сразу после создания экземпляра. Вышеприведенное выражение else показывает, что предыдущие разработчики ранее сталкивались с подобными ситуациями. Конечно, оригинальные разработчики давно прошли. Итак, мы хотели бы знать, может ли среда CLR создавать экземпляр объекта после вызова конструктора и возвращать нуль? Мы не знаем о такой возможности.

4b9b3361

Ответ 1

На мой взгляд, то, что предлагает оператор else, заключается в том, что предыдущие разработчики не знали своего С#. Конструктор всегда возвращает построенный объект или генерирует исключение.

В очень старые времена конструкторы С++ могли возвращать null, поэтому, возможно, проблема исходит из этого. Это больше не относится к С++, по крайней мере, для оператора new по умолчанию.

Ответ 2

Изменить: для пояснения есть сумасшедший край, где вы можете получить null из конструктора класса, но, честно говоря, я не думаю, что какой-либо реальный код должен когда-либо ожидать, чтобы справиться с этим уровнем сумасшествия: Какой самый странный угол, который вы видели на С# или .NET?. Для всех нормальных намерений: этого не произойдет.


Нет, вы не можете получить null из конструктора class (Thread - это класс). Единственный случай, когда я знаю, где конструктор может возвратиться null Nullable<T> - i.e.

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

Это несколько большая проблема с дженериками:

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

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

(конечно, есть способы проверить/обработать этот сценарий, например : class)

Кроме этого, конструктор всегда либо возвращает объект (или инициализирует структуру), либо генерирует исключение.

Ответ 3

НЕТ! эта нулевая проверка избыточна. Многие разработчики С++, которые переехали на С#, имеют эту привычку с нулевой проверкой, и я думаю, что здесь то же самое.

Единственное, что вы должны проверить документацию, чтобы увидеть, может ли конструктор выбросить любое исключение. В вашем случае обратитесь к http://msdn.microsoft.com/en-us/library/xx3ezzs2.aspx, и, как упоминалось, конструктор всегда будет возвращать действительный объект.