Peut-constructeur de l'objet renvoie null?
Nous avons pris le contrôle de certaines .NET 1.1 Service Windows de code qui génère des threads de lire les messages d'une file d'attente (SeeBeyond eGate file d'attente JMS, mais ce n'est pas important) et à son tour, engendre des threads pour traiter le message dans l'application cible de service. Nous sommes continuellement à la rencontre de la logique et les décisions de conception qui est curieux que nous, à n'en pas finir. Voici un exemple, où le message (lsMessage) a été récupéré à partir de la file d'attente et prêt pour le traitement
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;
}
}
S'il vous plaît ignorer la utilisation d'étiquettes et goto pour le moment, ce n'est pas la question. Notre perplexité est le vérifier si le Fil de l'objet est null juste après l'instanciation. L'instruction else ci-dessous semble suggérer la précédente, les développeurs ont rencontré des situations comme ça avant. Bien sûr, les développeurs à l'origine ont disparu depuis longtemps. Nous voudrions donc savoir, peut le CLR vraiment instancier un objet après l'appel au constructeur et renvoie null? Nous n'avons pas connaissance d'une telle possibilité.
- Regarde le résultat d'un refactoring de code ou de changement pour moi. Peut-être la construction de la ligne a autre chose comme
GetThread()
.
Vous devez vous connecter pour publier un commentaire.
À mon avis, ce que le
else
déclaration suggère est que les développeurs ne savent pas leur C#. Un constructeur renvoie toujours un objet construit ou lève une exception.Dans des temps très anciens, C++ constructeurs pourraient retourner
null
, alors peut-être que le problème vient de là. Ce n'est plus vrai en C++, au moins pour la valeur par défautnew
opérateur.Edit: pour clarifier, il est un fou de cas de bord où vous pouvez obtenir
null
à partir d'un constructeur de la classe, mais franchement, je ne pense pas que tout le code réel devrait jamais s'attendre à traiter avec ce niveau de fou: Ce qui est le plus étrange cas de coin vous avez vu en C# ou .NET? . Pour tous les normal intentions : il ne se produira pas.Non, vous ne pouvez pas obtenir nulle à partir d'un classe constructeur (
Thread
est une classe). Le seul cas que je connaisse où un constructeur peut (semble) retournull
estNullable<T>
- c'est à direC'est un peu plus gros problème avec les génériques:
(bien sûr, il existe des moyens de contrôle/de la manipulation de ce scénario, comme
: class
)Autre que cela, un constructeur de toujours retourner un objet (ou d'initialiser une structure), ou lever une exception.
class
, vous obtenez l'Erreur "1 Ne peut pas passer '<ce> "comme une ref ou un argument parce qu'elle est en lecture seule". Dans le cas d'unstruct
, leref
est bien, mais vous ne pouvez pas définir destruct
ànull
(sauf pourNullable<T>
, et vous ne contrôlez pas le constructeur deNullable<T>
)null
constructeur: stackoverflow.com/questions/194484/... - mais très peu probable de voir que dans le code réel.PAS! que nul case est redondante. Beaucoup de C++ devs qui a déménagé à la C# ont cette habitude de null check et je suppose que c'est la même chose ici.
La seule chose est, vous devriez vérifier la documentation pour voir si le constructeur peut lancer une exception. Dans votre cas, reportez-vous à http://msdn.microsoft.com/en-us/library/xx3ezzs2.aspx et comme l'indique le constructeur retournera toujours valide obj.
Vous pouvez le faire apparaître comme un objet ctor renvoie la valeur null:
http://seattlesoftware.wordpress.com/2008/03/05/returning-null-from-a-class-constructor/
De la recherche pour "Autre motif que je n'ai pas vu utilisé permet un objet non valide pour émuler une référence null" et lire à partir de là.
Comme
core
mentionne, la surcharge d'opérateur peut faire apparaître qu'un constructeur retournénull
, quand ce n'est pas ce qui s'est vraiment passé. Les auteurs de l'articlecore
trouvé disent qu'ils n'ont pas vu utilisé, mais il est effectivement utilisé dans un produit très populaire: l'Unité.Cela permettra de compiler et enregistrer un message au moment de l'exécution:
Maintenant, ici, la faute est mienne, parce que l'on devrait pas appeler le
AudioSource
constructeur directement. Mais un devrait savoir que le==
opérateur est surchargé à la racine de l'arbre d'héritage pour les objets de l'Unité de référence. Voici ce que l'Unité manuel dit à propos deUnityEngine.Object
's==
opérateur:Tandis que l'instanciation d'un
GameObject
l'initialise, l'instanciation d'unAudioSource
objet n'est pas, de sorte que la comparaison avecnull
retournetrue
.Cette étrange idiome est fait encore plus discret, en vertu du fait que tente de faire référence à des propriétés de la non initialisée
AudioSource
objet de jeter null-les exceptions de référence, qui au départ, j'ai mal interprété le sens de la référence d'objet a éténull
, pas la propriété.D'autres ont répondu à l'OP de la question, mais je voulais ajouter cette réponse parce que l'OP du code peut réellement de sens que si les
Thread
classe y n'est pas celle que nous nous attendons à être, tout commeObject
(et ses descendants) n'est pas du tout ce à quoi vous pouvez vous attendre qu'il soit dans une Unité de script (qui est, il est en faitUnityEngine.Object
, plutôt que deSystem.Object
, ce qui vous obtient la surcharge==
opérateur que si confus moi).