Chers futurs visiteurs, les réponses à cette question s'appliquent également à une ArgumentNullException . Si votre question a été fermée en double de celle-ci et que vous rencontrez une ANE, veuillez suivre les instructions dans les réponses pour déboguer et résoudre votre problème.
@will ANE ne devrait se produire que si une valeur NULL est passée en tant que paramètre. Pouvez-vous donner un exemple si une question de l'ANE s'est terminée en double de celle-ci?
John Saunders
Il est venu sur Meta, mais je devrais aller chercher le lien. Mais en ce qui concerne ce commentaire, un ANE est simplement un NRE mais quelqu'un a ajouté un contrôle préemptif, et vous savez au moins exactement ce qui est nul (le nom de l'argument est fourni), il est donc un peu plus facile à diagnostiquer qu'un NRE direct.
Réponses:
2417
Quelle est la cause?
Bottom Line
Vous essayez d'utiliser quelque chose qui est null(ou Nothingdans VB.NET). Cela signifie que vous le définissez nullou que vous ne le définissez jamais du tout.
Comme toute autre chose, se nullfait passer. S'il se trouve nulldans la méthode "A", il se peut que la méthode "B" soit passée nullà la méthode "A".
null peut avoir différentes significations:
Variables d'objet qui ne sont pas initialisées et ne pointent donc vers rien. Dans ce cas, si vous accédez aux propriétés ou aux méthodes de ces objets, cela provoque a NullReferenceException.
Le développeur utilise nullintentionnellement pour indiquer qu'aucune valeur significative n'est disponible. Notez que C # a le concept de types de données nullables pour les variables (comme les tables de base de données peuvent avoir des champs nullables) - vous pouvez leur affecter nullpour indiquer qu'il n'y a pas de valeur stockée dedans, par exemple int? a = null;lorsque le point d'interrogation indique qu'il est autorisé à stocker null dans variable a. Vous pouvez vérifier cela avec if (a.HasValue) {...}ou avec if (a==null) {...}. Les variables nulles, comme acet exemple, permettent d'accéder à la valeur via a.Valueexplicitement, ou tout simplement via via a. Notez que y accéder via a.Valuelance un InvalidOperationExceptionau lieu d'un NullReferenceExceptionif aestnull- vous devez faire la vérification au préalable, c'est-à-dire que si vous avez une autre variable on-nullable int b;alors vous devez faire des affectations comme if (a.HasValue) { b = a.Value; }ou plus courtes if (a != null) { b = a; }.
Le reste de cet article va plus en détail et montre les erreurs que de nombreux programmeurs font souvent et qui peuvent conduire à un NullReferenceException.
Plus précisement
Le runtimejetant un NullReferenceExceptiontoujours signifie la même chose: vous essayez d'utiliser une référence, et la référence n'est pas initialisé (ou il a été une fois initialisé, mais il est plus initialisé).
Cela signifie que la référence est nullet que vous ne pouvez pas accéder aux membres (tels que les méthodes) via une nullréférence. Le cas le plus simple:
string foo =null;
foo.ToUpper();
Cela lancera un NullReferenceExceptionà la deuxième ligne car vous ne pouvez pas appeler la méthode d'instance ToUpper()sur une stringréférence pointant vers null.
Débogage
Comment trouvez-vous la source d'un NullReferenceException? En plus de regarder l'exception elle-même, qui sera levée exactement à l'endroit où elle se produit, les règles générales de débogage dans Visual Studio s'appliquent: placez des points d'arrêt stratégiques et inspectez vos variables , soit en passant la souris sur leurs noms, en ouvrant un ( Rapide) Regardez la fenêtre ou utilisez les divers panneaux de débogage comme les sections locales et les automobiles.
Si vous souhaitez savoir où la référence est ou n'est pas définie, cliquez avec le bouton droit sur son nom et sélectionnez "Rechercher toutes les références". Vous pouvez ensuite placer un point d'arrêt à chaque emplacement trouvé et exécuter votre programme avec le débogueur attaché. Chaque fois que le débogueur s'arrête sur un tel point d'arrêt, vous devez déterminer si vous vous attendez à ce que la référence soit non nulle, inspecter la variable et vérifier qu'elle pointe vers une instance lorsque vous vous y attendez.
En suivant le flux du programme de cette façon, vous pouvez trouver l'emplacement où l'instance ne doit pas être nulle et pourquoi elle n'est pas correctement définie.
Exemples
Quelques scénarios courants où l'exception peut être levée:
Générique
ref1.ref2.ref3.member
Si ref1 ou ref2 ou ref3 est nul, vous obtiendrez a NullReferenceException. Si vous souhaitez résoudre le problème, recherchez celui qui est nul en réécrivant l'expression dans son équivalent le plus simple:
Plus précisément, dans HttpContext.Current.User.Identity.Name, le HttpContext.Currentpourrait être nul, ou la Userpropriété pourrait être nulle, ou la Identitypropriété pourrait être nulle.
Indirect
publicclassPerson{publicintAge{get;set;}}publicclassBook{publicPersonAuthor{get;set;}}publicclassExample{publicvoidFoo(){Book b1 =newBook();int authorAge = b1.Author.Age;// You never initialized the Author property.// there is no Person to get an Age from.}}
Si vous souhaitez éviter la référence null enfant (Personne), vous pouvez l'initialiser dans le constructeur de l'objet parent (Livre).
Initialiseurs d'objets imbriqués
La même chose s'applique aux initialiseurs d'objets imbriqués:
Book b1 =newBook{Author={Age=45}};
Cela se traduit par
Book b1 =newBook();
b1.Author.Age=45;
Pendant que le newmot-clé est utilisé, il crée seulement une nouvelle instance de Book, mais pas une nouvelle instance de Person, donc Authorla propriété est toujours null.
La collection imbriquée Initializersse comporte de la même manière:
Person p1 =newPerson{Books={newBook{Title="Title1"},newBook{Title="Title2"},}};
Cela se traduit par
Person p1 =newPerson();
p1.Books.Add(newBook{Title="Title1"});
p1.Books.Add(newBook{Title="Title2"});
La new Personseule crée une instance de Person, mais la Bookscollection est toujours null. La Initializersyntaxe de collection ne crée pas de collection pour p1.Books, elle se traduit uniquement par les p1.Books.Add(...)instructions.
Array
int[] numbers =null;int n = numbers[0];// numbers is null. There is no array to index.
Éléments du tableau
Person[] people =newPerson[5];
people[0].Age=20// people[0] is null. The array was allocated but not// initialized. There is no Person to set the Age for.
Tableaux dentelés
long[][] array =newlong[1][];
array[0][0]=3;// is null because only the first dimension is yet initialized.// Use array[0] = new long[2]; first.
Collection / Liste / Dictionnaire
Dictionary<string,int> agesForNames =null;int age = agesForNames["Bob"];// agesForNames is null.// There is no Dictionary to perform the lookup.
Variable de plage (indirecte / différée)
publicclassPerson{publicstringName{get;set;}}var people =newList<Person>();
people.Add(null);var names =from p in people select p.Name;string firstName = names.First();// Exception is thrown here, but actually occurs// on the line above. "p" is null because the// first element we added to the list is null.
Événements
publicclassDemo{publiceventEventHandlerStateChanged;protectedvirtualvoidOnStateChanged(EventArgs e){StateChanged(this, e);// Exception is thrown here // if no event handlers have been attached// to StateChanged event}}###Bad Naming Conventions:If you named fields differently from locals, you might have realized that you never initialized the field.
Cela peut être résolu en suivant la convention pour préfixer les champs avec un trait de soulignement:
privateCustomer _customer;
Cycle de vie de la page ASP.NET:
publicpartialclassIssues_Edit:System.Web.UI.Page{protectedTestIssue myIssue;protectedvoidPage_Load(object sender,EventArgs e){if(!IsPostBack){// Only called on first load, not when button clicked
myIssue =newTestIssue();}}protectedvoidSaveButton_Click(object sender,EventArgs e){
myIssue.Entry="NullReferenceException here!";}}
Valeurs de session ASP.NET
// if the "FirstName" session value has not yet been set,// then this line will throw a NullReferenceExceptionstring firstName =Session["FirstName"].ToString();
Modèles de vues vides ASP.NET MVC
Si l'exception se produit lors du référencement d'une propriété de @Modeldans un ASP.NET MVC View, vous devez comprendre que le Modelget est défini dans votre méthode d'action, lorsque vous returnune vue. Lorsque vous renvoyez un modèle vide (ou une propriété de modèle) à partir de votre contrôleur, l'exception se produit lorsque les vues y accèdent:
// ControllerpublicclassRestaurant:Controller{publicActionResultSearch(){returnView();// Forgot the provide a Model here.}}// Razor view @foreach(var restaurantSearch inModel.RestaurantSearch)// Throws.{}<p>@Model.somePropertyName</p><!--Alsothrows-->
Ordre et événements de création de contrôle WPF
WPFles contrôles sont créés lors de l'appel à InitializeComponentdans l'ordre dans lequel ils apparaissent dans l'arborescence visuelle. Un NullReferenceExceptionsera soulevé dans le cas de contrôles créés au début avec des gestionnaires d'événements, etc., qui se déclenchent pendant InitializeComponentlesquels référencent les contrôles créés tardivement.
Par exemple :
<Grid><!-- Combobox declared first --><ComboBoxName="comboBox1"Margin="10"SelectedIndex="0"SelectionChanged="comboBox1_SelectionChanged"><ComboBoxItemContent="Item 1"/><ComboBoxItemContent="Item 2"/><ComboBoxItemContent="Item 3"/></ComboBox><!-- Label declared later --><LabelName="label1"Content="Label"Margin="10"/></Grid>
Ici comboBox1est créé avant label1. Si comboBox1_SelectionChangedvous essayez de référencer `label1, il n'aura pas encore été créé.
Changer l'ordre des déclarations dans le XAML(c.-à-d., Énumérer label1avant comboBox1, ignorer les problèmes de philosophie de conception, résoudrait au moins l' NullReferenceExceptionici.
Cast avec as
var myThing = someObject asThing;
Cela ne lance pas un InvalidCastExceptionmais renvoie un nulllorsque le transtypage échoue (et quand someObjectest lui-même nul). Soyez donc conscient de cela.
LINQ FirstOrDefault()etSingleOrDefault()
Les versions simples First()et Single()lèvent des exceptions quand il n'y a rien. Les versions "OrDefault" renvoient null dans ce cas. Soyez donc conscient de cela.
pour chaque
foreachjette lorsque vous essayez d'itérer la collection null. Habituellement provoqué par un nullrésultat inattendu des méthodes qui retournent des collections.
List<int> list =null;foreach(var v in list){}// exception
Exemple plus réaliste - sélectionnez des nœuds dans un document XML. Jettera si les nœuds ne sont pas trouvés mais le débogage initial montre que toutes les propriétés valides:
foreach(var node in myData.MyXml.DocumentNode.SelectNodes("//Data"))
Façons à éviter
Vérifiez nullet ignorez explicitement les valeurs nulles.
Si vous vous attendez à ce que la référence soit parfois nulle, vous pouvez vérifier qu'elle est nullavant d'accéder aux membres de l'instance:
Recherchez nullet fournissez explicitement une valeur par défaut.
Les méthodes que vous prévoyez de renvoyer peuvent renvoyer une instance null, par exemple lorsque l'objet recherché est introuvable. Vous pouvez choisir de renvoyer une valeur par défaut lorsque c'est le cas:
Recherchez explicitement les nullappels de méthode et lancez une exception personnalisée.
Vous pouvez également lever une exception personnalisée, uniquement pour l'attraper dans le code appelant:
stringGetCategory(string bookTitle){var book = library.FindBook(bookTitle);// This may return nullif(book ==null)thrownewBookNotFoundException(bookTitle);// Your custom exceptionreturn book.Category;}
À utiliser Debug.Assertsi une valeur ne doit jamais l'être null, pour détecter le problème avant que l'exception ne se produise.
Lorsque vous savez pendant le développement qu'une méthode peut peut-être, mais ne devrait jamais revenir null, vous pouvez utiliser Debug.Assert()pour interrompre dès que possible quand elle se produit:
stringGetTitle(int knownBookID){// You know this should never return null.var book = library.GetBook(knownBookID);// Exception will occur on the next line instead of at the end of this method.Debug.Assert(book !=null,"Library didn't return a book for known book ID.");// Some other codereturn book.Title;// Will never throw NullReferenceException in Debug mode.}
Bien que cette vérification ne se termine pas dans votre version , ce qui la fait lancer à NullReferenceExceptionnouveau lors book == nullde l'exécution en mode de publication.
Utilisez GetValueOrDefault()pour les nullabletypes de valeur pour fournir une valeur par défaut lorsqu'ils le sont null.
DateTime? appointment =null;Console.WriteLine(appointment.GetValueOrDefault(DateTime.Now));// Will display the default value provided (DateTime.Now), because appointment is null.
appointment =newDateTime(2022,10,20);Console.WriteLine(appointment.GetValueOrDefault(DateTime.Now));// Will display the appointment date, not the default
Utilisez l'opérateur de coalescence nul: ??[C #] ou If()[VB].
Le raccourci pour fournir une valeur par défaut quand un nullest rencontré:
IServiceCreateService(ILogger log,Int32? frobPowerLevel){var serviceImpl =newMyService(log ??NullLog.Instance);// Note that the above "GetValueOrDefault()" can also be rewritten to use// the coalesce operator:
serviceImpl.FrobPowerLevel= frobPowerLevel ??5;}
Utilisez l'opérateur de condition nulle: ?.ou ?[x]pour les tableaux (disponibles en C # 6 et VB.NET 14):
On l'appelle aussi parfois l'opérateur de navigation sécurisée ou Elvis (d'après sa forme). Si l'expression sur le côté gauche de l'opérateur est nulle, le côté droit ne sera pas évalué et null sera renvoyé à la place. Cela signifie des cas comme celui-ci:
var title = person.Title.ToUpper();
Si la personne n'a pas de titre, cela lèvera une exception car elle essaie d'appeler ToUpperune propriété avec une valeur nulle.
Dans C# 5et en dessous, cela peut être gardé avec:
var title = person.Title==null?null: person.Title.ToUpper();
Maintenant, la variable de titre sera nulle au lieu de lever une exception. C # 6 introduit une syntaxe plus courte pour cela:
var title = person.Title?.ToUpper();
Cela se traduira par la variable de titre étant null, et l'appel à ToUppern'est pas effectué si person.Titleest null.
Bien sûr, vous devez toujours vérifier titlenull ou utiliser l'opérateur de condition null avec l'opérateur de coalescence null ( ??) pour fournir une valeur par défaut:
// regular null checkint titleLength =0;if(title !=null)
titleLength = title.Length;// If title is null, this would throw NullReferenceException// combining the `?` and the `??` operatorint titleLength = title?.Length??0;
De même, pour les tableaux, vous pouvez utiliser ?[i]comme suit:
Cela fera ce qui suit: Si myIntArrayest null, l'expression renvoie null et vous pouvez le vérifier en toute sécurité. S'il contient un tableau, il fera la même chose que:
elem = myIntArray[i];et renvoie l' i<sup>th</sup>élément.
Utilisez un contexte nul (disponible en C # 8):
Introduits dans C# 8ce contexte, les types de contexte nullable et de référence nullable effectuent une analyse statique sur les variables et fournissent un avertissement du compilateur si une valeur peut être potentiellement nulle ou avoir été définie sur null. Les types de référence nullable permettent aux types d'être explicitement autorisés à être null.
Le contexte d'annotation nullable et le contexte d'avertissement nullable peuvent être définis pour un projet à l'aide de l' Nullableélément dans votre csprojfichier. Cet élément configure la façon dont le compilateur interprète la nullité des types et quels avertissements sont générés. Les paramètres valides sont:
enable: le contexte d'annotation annulable est activé. Le contexte d'avertissement nullable est activé. Les variables d'un type de référence, chaîne par exemple, ne sont pas nullables. Tous les avertissements de nullité sont activés.
disable: le contexte d'annotation annulable est désactivé. Le contexte d'avertissement nullable est désactivé. Les variables d'un type de référence sont inconscientes, tout comme les versions antérieures de C #. Tous les avertissements de nullité sont désactivés.
safeonly: le contexte d'annotation nullable est activé. Le contexte d'avertissement nullable est sécurisé uniquement. Les variables d'un type de référence sont non nulles. Tous les avertissements de nullité de sécurité sont activés.
avertissements: le contexte d'annotation annulable est désactivé. Le contexte d'avertissement nullable est activé. Les variables d'un type de référence sont inconscientes. Tous les avertissements de nullité sont activés.
safeonlywarnings: le contexte d'annotation nullable est désactivé. Le contexte d'avertissement nullable est sécurisé uniquement. Les variables d'un type de référence sont inconscientes. Tous les avertissements de nullité de sécurité sont activés.
Un type de référence nullable est noté en utilisant la même syntaxe que les types de valeur nullable: a ?est ajouté au type de la variable.
Techniques spéciales pour déboguer et corriger les derefs nuls dans les itérateurs
C#prend en charge les "blocs d'itérateur" (appelés "générateurs" dans d'autres langues populaires). Les exceptions de déréférencement nul peuvent être particulièrement difficiles à déboguer dans les blocs d'itérateur en raison de l'exécution différée:
publicIEnumerable<Frob>GetFrobs(FrobFactory f,int count){for(int i =0; i < count;++i)yieldreturn f.MakeFrob();}...FrobFactory factory = whatever;IEnumerable<Frobs> frobs =GetFrobs();...foreach(Frob frob in frobs){...}
Si les whateverrésultats en nullpuis MakeFrobjettera. Maintenant, vous pourriez penser que la bonne chose à faire est la suivante:
// DON'T DO THISpublicIEnumerable<Frob>GetFrobs(FrobFactory f,int count){if(f ==null)thrownewArgumentNullException("f","factory must not be null");for(int i =0; i < count;++i)yieldreturn f.MakeFrob();}
Pourquoi est-ce mal? Parce que le bloc itérateur ne s'exécute pas tant que le foreach! L'appel à GetFrobsrenvoie simplement un objet qui, une fois itéré , exécutera le bloc itérateur.
En écrivant une vérification nulle comme celle-ci, vous empêchez la déréférence nulle, mais vous déplacez l'exception d'argument nul au point de l' itération , pas au point de l' appel , ce qui est très déroutant pour le débogage .
La solution correcte est:
// DO THISpublicIEnumerable<Frob>GetFrobs(FrobFactory f,int count){// No yields in a public method that throws!if(f ==null)thrownewArgumentNullException("f","factory must not be null");returnGetFrobsForReal(f, count);}privateIEnumerable<Frob>GetFrobsForReal(FrobFactory f,int count){// Yields in a private methodDebug.Assert(f !=null);for(int i =0; i < count;++i)yieldreturn f.MakeFrob();}
Autrement dit, créez une méthode d'assistance privée qui a la logique de blocage de l'itérateur et une méthode de surface publique qui effectue la vérification nulle et renvoie l'itérateur. Maintenant, quand GetFrobsest appelé, la vérification nulle se produit immédiatement, puis GetFrobsForReals'exécute lorsque la séquence est itérée.
Si vous examinez la source de référence pour LINQto Objects, vous verrez que cette technique est utilisée partout. Il est légèrement plus maladroit à écrire, mais il facilite beaucoup le débogage des erreurs de nullité. Optimisez votre code pour la commodité de l'appelant et non pour la commodité de l'auteur .
Une note sur les déréférences nulles dans le code dangereux
C#a un mode "dangereux" qui est, comme son nom l'indique, extrêmement dangereux car les mécanismes de sécurité normaux qui assurent la sécurité de la mémoire et la sécurité du type ne sont pas appliqués. Vous ne devez pas écrire de code dangereux à moins d'avoir une compréhension approfondie et approfondie du fonctionnement de la mémoire .
En mode non sécurisé, vous devez être conscient de deux faits importants:
déréférencer un pointeur nul produit la même exception que déréférencer une référence nulle
déréférencer un pointeur non nul non valide peut produire cette exception dans certaines circonstances
Pour comprendre pourquoi, il est utile de comprendre comment .NET produit en premier lieu des exceptions de déréférencement nul. (Ces détails s'appliquent à .NET exécuté sur Windows; d'autres systèmes d'exploitation utilisent des mécanismes similaires.)
La mémoire est virtualisée dans Windows; chaque processus obtient un espace de mémoire virtuelle de nombreuses "pages" de mémoire qui sont suivies par le système d'exploitation. Chaque page de mémoire comporte des indicateurs qui déterminent comment elle peut être utilisée: lecture, écriture, exécution, etc. La page la plus basse est marquée comme "produire une erreur si jamais utilisée de quelque façon que ce soit".
Un pointeur nul et une référence nulle dans C#sont représentés en interne sous la forme du nombre zéro, et donc toute tentative de déréférencement dans son stockage mémoire correspondant entraîne une erreur du système d'exploitation. Le runtime .NET détecte ensuite cette erreur et la transforme en exception de déréférence nulle.
C'est pourquoi le déréférencement d'un pointeur nul et d'une référence nulle produit la même exception.
Et le deuxième point? Le déréférencement de tout pointeur non valide qui tombe dans la page la plus basse de la mémoire virtuelle provoque la même erreur du système d'exploitation, et donc la même exception.
Pourquoi est-ce logique? Supposons que nous ayons une structure contenant deux entrées et un pointeur non géré égal à null. Si nous essayons de déréférencer le deuxième entier dans la structure, le CLRne tentera pas d'accéder au stockage à l'emplacement zéro; il accédera au stockage à l'emplacement quatre. Mais logiquement, c'est une déréférence nulle parce que nous arrivons à cette adresse via la valeur nulle.
Si vous travaillez avec du code dangereux et que vous obtenez une exception de déréférence nulle, sachez simplement que le pointeur incriminé n'a pas besoin d'être nul. Il peut s'agir de n'importe quel emplacement dans la page la plus basse et cette exception sera produite.
Peut-être que c'est un commentaire stupide, mais la première et meilleure façon d'éviter ce problème ne serait-elle pas d'initialiser l'objet? Pour moi, si cette erreur se produit, c'est généralement parce que j'ai oublié d'initialiser quelque chose comme l'élément de tableau. Je pense qu'il est beaucoup moins courant de définir l'objet comme nul et de le référencer ensuite. Peut-être donner le moyen de résoudre chaque problème adjacent à la description. Encore un bon post.
JPK
30
Et s'il n'y a pas d'objet, mais plutôt la valeur de retour d'une méthode ou d'une propriété?
John Saunders
6
L'exemple livre / auteur est un peu bizarre .... Comment ça compile même? Comment fonctionne Intellisense même? Qu'est-ce que je ne suis pas bon avec computar ...
5
@ Will: ma dernière édition aide-t-elle? Sinon, veuillez être plus explicite sur ce que vous voyez comme un problème.
John Saunders, le
6
@JohnSaunders Oh, non, désolé, je voulais dire la version initialiseur d'objet de cela. new Book { Author = { Age = 45 } };Comment l'initialisation interne fonctionne-t-elle même ... Je ne peux pas penser à une situation où l'init interne fonctionnerait jamais, mais il compile et l'intellisense fonctionne ... Sauf pour les structures?
311
Exception NullReference - Visual Basic
Le NullReference Exceptionpour Visual Basic n'est pas différent de celui en C # . Après tout, ils signalent tous deux la même exception définie dans le .NET Framework qu'ils utilisent tous les deux. Les causes propres à Visual Basic sont rares (peut-être une seule).
Cette réponse utilisera les termes, la syntaxe et le contexte Visual Basic. Les exemples utilisés proviennent d'un grand nombre de questions sur le débordement de pile passées. Il s'agit de maximiser la pertinence en utilisant les types de situations souvent vues dans les publications. Un peu plus d'explications sont également fournies pour ceux qui pourraient en avoir besoin. Un exemple similaire au vôtre est très probablement répertorié ici.
Remarque:
C'est basé sur le concept: il n'y a pas de code à coller dans votre projet. Il est destiné à vous aider à comprendre ce qui cause un NullReferenceException(NRE), comment le trouver, comment le réparer et comment l'éviter. Un NRE peut être causé de plusieurs façons, il est donc peu probable que ce soit votre seule rencontre.
Les exemples (tirés des publications Stack Overflow) ne montrent pas toujours la meilleure façon de faire quelque chose en premier lieu.
En règle générale, le remède le plus simple est utilisé.
Signification de base
Le message "Objet non défini sur une instance d'Objet" signifie que vous essayez d'utiliser un objet qui n'a pas été initialisé. Cela se résume à l'un d'eux:
Votre code a déclaré une variable objet, mais il ne l'a pas initialisée (créez une instance ou « instanciez-la »)
Quelque chose que votre code supposait initialiserait un objet, n'a pas
Peut-être, un autre code a invalidé prématurément un objet encore utilisé
Trouver la cause
Puisque le problème est une référence d'objet qui est Nothing, la réponse est de les examiner pour trouver lequel. Déterminez ensuite pourquoi il n'est pas initialisé. Maintenez la souris sur les différentes variables et Visual Studio (VS) affichera leurs valeurs - le coupable sera Nothing.
Vous devez également supprimer tous les blocs Try / Catch du code pertinent, en particulier ceux où il n'y a rien dans le bloc Catch. Cela provoquera le plantage de votre code lorsqu'il essaie d'utiliser un objet qui l'est Nothing. C'est ce que vous voulez car il identifiera l' emplacement exact du problème et vous permettra d'identifier l'objet à l'origine de ce problème.
Un MsgBoxin the Catch qui s'affiche Error while...ne sera d'aucune utilité. Cette méthode conduit également à de très mauvaises questions de débordement de pile, car vous ne pouvez pas décrire l'exception réelle, l'objet impliqué ou même la ligne de code où elle se produit.
Vous pouvez également utiliser le Locals Window( Débogage -> Windows -> Locaux ) pour examiner vos objets.
Une fois que vous savez quel est et où est le problème, il est généralement assez facile à résoudre et plus rapide que de poster une nouvelle question.
Dim reg As CashRegister
...
TextBox1.Text = reg.Amount ' NRE
Le problème est qu'il Dimne crée pas d' objet CashRegister ; il déclare uniquement une variable nommée regde ce type. La déclaration d' une variable d'objet et la création d'une instance sont deux choses différentes.
Remède
L' Newopérateur peut souvent être utilisé pour créer l'instance lorsque vous la déclarez:
Dim reg AsNew CashRegister ' [New] creates instance, invokes the constructor' Longer, more explicit form:Dim reg As CashRegister =New CashRegister
Lorsqu'il ne convient que de créer l'instance ultérieurement:
Remarque: Ne réutilisez Dimpas dans une procédure, y compris le constructeur ( Sub New):
Private reg As CashRegister
'...PublicSubNew()'...Dim reg AsNew CashRegister
EndSub
Cela va créer une variable localereg , qui n'existe que dans ce contexte (sub). La regvariable de niveau module Scopeque vous utiliserez partout ailleurs reste Nothing.
L' Newopérateur manquant est la cause n ° 1 desNullReference Exceptions problèmes de débordement de pile examinés.
Visual Basic essaie de rendre le processus clair à plusieurs reprises en utilisant New: L'utilisation de l' Newopérateur crée un nouvel objet et appelle Sub New- le constructeur - où votre objet peut effectuer toute autre initialisation.
Pour être clair, Dim(ou Private) ne déclare qu'une variable et son Type. L' étendue de la variable - qu'elle existe pour l'ensemble du module / de la classe ou qu'elle soit locale à une procédure - est déterminée par l' endroit où elle est déclarée. Private | Friend | Publicdéfinit le niveau d'accès, pas la portée .
Ce tableau a seulement été déclaré, pas créé. Il existe plusieurs façons d'initialiser un tableau:
Private arr asString()=NewString(10){}' orPrivate arr()AsString=NewString(10){}' For a local array (in a procedure) and using 'Option Infer':Dim arr =NewString(10){}
Remarque: à partir de VS 2010, lors de l'initialisation d'un tableau local à l'aide d'un littéral et Option Infer, les éléments As <Type>et Newsont facultatifs:
Dim myDbl AsDouble()={1.5,2,9.9,18,3.14}Dim myDbl =NewDouble(){1.5,2,9.9,18,3.14}Dim myDbl()={1.5,2,9.9,18,3.14}
Le type de données et la taille du tableau sont déduits des données attribuées. Les déclarations de niveau de classe / module nécessitent toujours As <Type>avec Option Strict:
Private myDoubles AsDouble()={1.5,2,9.9,18,3.14}
Exemple: tableau d'objets de classe
Dim arrFoo(5)As Foo
For i AsInteger=0To arrFoo.Count -1
arrFoo(i).Bar = i *10' ExceptionNext
Le tableau a été créé, mais pas les Fooobjets qu'il contient .
Remède
For i AsInteger=0To arrFoo.Count -1
arrFoo(i)=New Foo()' Create Foo instance
arrFoo(i).Bar = i *10Next
Utiliser un List(Of T)rendra assez difficile d'avoir un élément sans objet valide:
Dim FooList AsNew List(Of Foo)' List created, but it is emptyDim f As Foo ' Temporary variable for the loopFor i AsInteger=0To5
f =New Foo()' Foo instance created
f.Bar = i *10
FooList.Add(f)' Foo object added to listNext
Les collections .NET (dont il existe de nombreuses variétés - listes, dictionnaire, etc.) doivent également être instanciées ou créées.
Private myList As List(Of String)..
myList.Add("ziggy")' NullReference
Vous obtenez la même exception pour la même raison - myListn'a été déclaré, mais aucune instance n'a été créée. Le remède est le même:
myList =New List(Of String)' Or create an instance when declared:Private myList AsNew List(Of String)
Un oubli commun est une classe qui utilise une collection Type:
PublicClass Foo
Private barList As List(Of Bar)FriendFunction BarCount AsIntegerReturn barList.Count
EndFunctionFriendSub AddItem(newBar As Bar)If barList.Contains(newBar)=FalseThen
barList.Add(newBar)EndIfEndFunction
L'une ou l'autre procédure se traduira par un NRE, car il barListest uniquement déclaré, et non instancié. La création d'une instance de Foone créera pas également une instance de l'interne barList. C'était peut-être l'intention de le faire dans le constructeur:
PublicSubNew' Constructor' Stuff to do when a new Foo is created...
barList =New List(Of Bar)EndSub
Comme précédemment, c'est incorrect:
PublicSubNew()' Creates another barList local to this procedureDim barList AsNew List(Of Bar)EndSub
Travailler avec des bases de données présente de nombreuses possibilités pour une NullReference car il peut y avoir de nombreux objets ( Command, Connection, Transaction, Dataset, DataTable, DataRows....) en usage à la fois. Remarque: Peu importe le fournisseur de données que vous utilisez - MySQL, SQL Server, OleDB, etc. - les concepts sont les mêmes.
Exemple 1
Dim da As OleDbDataAdapter
Dim ds As DataSet
Dim MaxRows AsInteger
con.Open()Dim sql ="SELECT * FROM tblfoobar_List"
da =New OleDbDataAdapter(sql, con)
da.Fill(ds,"foobar")
con.Close()
MaxRows = ds.Tables("foobar").Rows.Count ' Error
Comme précédemment, l' dsobjet Dataset a été déclaré, mais aucune instance n'a été créée. Le DataAdapterremplira un existant DataSet, pas en créer un. Dans ce cas, puisqu'il dss'agit d'une variable locale, l'EDI vous avertit que cela peut se produire:
Lorsqu'il est déclaré en tant que variable de niveau module / classe, comme cela semble être le cas con, le compilateur ne peut pas savoir si l'objet a été créé par une procédure en amont. N'ignorez pas les avertissements.
Une faute de frappe est un problème ici: Employeesvs Employee. Aucun DataTable"employé" n'a été créé, donc un NullReferenceExceptionrésultat a tenté d'y accéder. Un autre problème potentiel est de supposer qu'il y en aura, ce Itemsqui peut ne pas être le cas lorsque le SQL inclut une clause WHERE.
Remède
Comme cela utilise une seule table, l'utilisation Tables(0)évitera les fautes d'orthographe. L'examen Rows.Countpeut également aider:
If ds.Tables(0).Rows.Count >0Then
txtID.Text = ds.Tables(0).Rows(0).Item(1)
txtID.Name = ds.Tables(0).Rows(0).Item(2)EndIf
Fillest une fonction renvoyant le nombre de personnes Rowsaffectées qui peut également être testée:
If da.Fill(ds,"Employees")>0Then...
Exemple 3
Dim da AsNew OleDb.OleDbDataAdapter("SELECT TICKET.TICKET_NO,
TICKET.CUSTOMER_ID, ... FROM TICKET_RESERVATION AS TICKET INNER JOIN
FLIGHT_DETAILS AS FLIGHT ... WHERE [TICKET.TICKET_NO]= ...", con)Dim ds AsNew DataSet
da.Fill(ds)If ds.Tables("TICKET_RESERVATION").Rows.Count >0Then
Le DataAdapterfournira TableNamescomme indiqué dans l'exemple précédent, mais il n'analyse pas les noms de la table SQL ou de la base de données. Par conséquent, ds.Tables("TICKET_RESERVATION")référence une table inexistante.
Le remède est le même, référencez le tableau par index:
Le code ne teste Itemsque les deux myFooet Barpeut également être Nothing. Le remède consiste à tester la chaîne ou le chemin complet des objets un par un:
AndAlsoest important. Les tests suivants ne seront pas effectués une fois la première Falsecondition rencontrée. Cela permet au code de «percer» en toute sécurité dans le (s) objet (s) un «niveau» à la fois, en évaluant myFoo.Baruniquement après (et si) myFooest déterminé comme étant valide. Les chaînes ou chemins d'objets peuvent devenir assez longs lors du codage d'objets complexes:
Ici, myWebBrowserou Documentpourrait être Nothing ou l' formfld1élément peut ne pas exister.
Contrôles de l'interface utilisateur
Dim cmd5 AsNew SqlCommand("select Cartons, Pieces, Foobar " _
&"FROM Invoice where invoice_no = '"& _
Me.ComboBox5.SelectedItem.ToString.Trim &"' And category = '"& _
Me.ListBox1.SelectedItem.ToString.Trim &"' And item_name = '"& _
Me.ComboBox2.SelectedValue.ToString.Trim &"' And expiry_date = '"& _
Me.expiry.Text &"'", con)
Entre autres choses, ce code ne prévoit pas que l'utilisateur n'a peut-être pas sélectionné quelque chose dans un ou plusieurs contrôles d'interface utilisateur. ListBox1.SelectedItempourrait bien être Nothing, il ListBox1.SelectedItem.ToStringen résultera un NRE.
Remède
Validez les données avant de les utiliser (utilisez également Option Strictles paramètres SQL et SQL):
Dim expiry As DateTime ' for text date validationIf(ComboBox5.SelectedItems.Count >0)AndAlso(ListBox1.SelectedItems.Count >0)AndAlso(ComboBox2.SelectedItems.Count >0)AndAlso(DateTime.TryParse(expiry.Text, expiry)Then'... do stuffElse
MessageBox.Show(...error message...)EndIf
Vous pouvez également utiliser (ComboBox5.SelectedItem IsNot Nothing) AndAlso...
Formulaires Visual Basic
PublicClass Form1
Private NameBoxes =New TextBox(5){Controls("TextBox1"), _
Controls("TextBox2"), Controls("TextBox3"), _
Controls("TextBox4"), Controls("TextBox5"), _
Controls("TextBox6")}' same thing in a different format:Private boxList AsNew List(Of TextBox) From {TextBox1, TextBox2, TextBox3 ...}' Immediate NRE:Private somevar AsString=Me.Controls("TextBox1").Text
Il s'agit d'un moyen assez courant d'obtenir un NRE. En C #, selon la façon dont il est codé, l'EDI signalera qu'il Controlsn'existe pas dans le contexte actuel ou "ne peut pas référencer un membre non statique". Donc, dans une certaine mesure, c'est une situation uniquement VB. Il est également complexe car il peut entraîner une cascade de pannes.
Les tableaux et les collections ne peuvent pas être initialisés de cette façon. Ce code d'initialisation s'exécutera avant que le constructeur ne crée le Formou le Controls. Par conséquent:
Les listes et la collection seront simplement vides
Le tableau contiendra cinq éléments de Nothing
L' somevaraffectation entraînera un NRE immédiat car rien n'a de .Textpropriété
Référencer les éléments du tableau ultérieurement entraînera un NRE. Si vous le faites dans Form_Load, en raison d'un bogue étrange, l'EDI peut ne pas signaler l'exception lorsqu'elle se produit. L'exception apparaîtra plus tard lorsque votre code essaie d'utiliser le tableau. Cette "exception silencieuse" est détaillée dans cet article . Pour nos besoins, la clé est que lorsque quelque chose de catastrophique se produit lors de la création d'un formulaire ( Sub Newou d'un Form Loadévénement), les exceptions peuvent ne pas être signalées, le code quitte la procédure et affiche simplement le formulaire.
Puisqu'aucun autre code dans votre événement Sub Newou Form Loadne s'exécutera après le NRE, de nombreuses autres choses peuvent être laissées non initialisées.
Sub Form_Load(..._
'...Dim name AsString= NameBoxes(2).Text ' NRE' ...' More code (which will likely not be executed)' ...EndSub
Notez que cela s'applique à toutes les références de contrôle et de composant qui les rendent illégales où elles se trouvent:
Il est curieux que VB ne fournit pas un avertissement, mais le remède est de déclarer les conteneurs au niveau de la forme, mais initialiser les dans le gestionnaire d'événement de chargement de formulaire lorsque les contrôles font exist. Cela peut être fait Sub Newtant que votre code est après l' InitializeComponentappel:
' Module level declarationPrivate NameBoxes as TextBox()Private studentName AsString' Form Load, Form Shown or Sub New:'' Using the OP's approach (illegal using OPTION STRICT)
NameBoxes =New TextBox(){Me.Controls("TextBox1"),Me.Controls("TestBox2"),...)
studentName = TextBox32.Text ' For simple control references
Le code du tableau n'est peut-être pas encore sorti du bois. Tous les contrôles qui sont dans un contrôle conteneur (comme un GroupBoxou Panel) ne seront pas trouvés dans Me.Controls; ils seront dans la collection Controls de ce Panel ou GroupBox. Un contrôle ne sera pas non plus renvoyé lorsque le nom du contrôle est mal orthographié ( "TeStBox2"). Dans de tels cas, Nothingsera à nouveau stocké dans ces éléments du tableau et un NRE sera généré lorsque vous tenterez de le référencer.
Ceux-ci devraient être faciles à trouver maintenant que vous savez ce que vous recherchez:
"Button2" réside sur un Panel
Remède
Plutôt que des références indirectes par nom à l'aide de la Controlscollection du formulaire , utilisez la référence de contrôle:
' DeclarationPrivate NameBoxes As TextBox()' Initialization - simple and easy to read, hard to botch:
NameBoxes =New TextBox(){TextBox1, TextBox2,...)' Initialize a List
NamesList =New List(Of TextBox)({TextBox1, TextBox2, TextBox3...})' or
NamesList =New List(Of TextBox)
NamesList.AddRange({TextBox1, TextBox2, TextBox3...})
Fonction ne retournant rien
Private bars AsNew List(Of Bars)' Declared and createdPublicFunction BarList()As List(Of Bars)
bars.Clear
If someCondition ThenFor n AsInteger=0to someValue
bars.Add(GetBar(n))Next n
ElseExitFunctionEndIfReturn bars
EndFunction
Il s'agit d'un cas où l'EDI vous avertira que « tous les chemins ne renvoient pas une valeur et NullReferenceExceptionpeuvent en résulter ». Vous pouvez supprimer l'avertissement, en le remplaçant Exit Functionpar Return Nothing, mais cela ne résout pas le problème. Tout ce qui tente d'utiliser le retour someCondition = Falseentraînera un NRE:
bList = myFoo.BarList()ForEach b As Bar in bList ' EXCEPTION...
Remède
Remplacez Exit Functionla fonction par Return bList. Retourner un videList n'est pas la même chose que retourner Nothing. S'il y a une chance qu'un objet retourné puisse l'être Nothing, testez avant de l'utiliser:
Un Try / Catch mal implémenté peut cacher où se trouve le problème et en entraîner de nouveaux:
Dim dr As SqlDataReader
TryDim lnk As LinkButton = TryCast(sender, LinkButton)Dim gr As GridViewRow =DirectCast(lnk.NamingContainer, GridViewRow)Dim eid AsString= GridView1.DataKeys(gr.RowIndex).Value.ToString()
ViewState("username")= eid
sqlQry ="select FirstName, Surname, DepartmentName, ExtensionName, jobTitle,
Pager, mailaddress, from employees1 where username='"& eid &"'"If connection.State <> ConnectionState.Open Then
connection.Open()EndIf
command =New SqlCommand(sqlQry, connection)'More code fooing and barring
dr = command.ExecuteReader()If dr.Read()Then
lblFirstName.Text = Convert.ToString(dr("FirstName"))...EndIf
mpe.Show()CatchFinally
command.Dispose()
dr.Close()' <-- NRE
connection.Close()EndTry
Il s'agit d'un cas où un objet n'est pas créé comme prévu, mais démontre également la contre-utilité d'un vide Catch.
Il y a une virgule supplémentaire dans le SQL (après 'mailaddress') qui entraîne une exception à .ExecuteReader. Après que le Catchne fait rien, Finallyessaie d'effectuer un nettoyage, mais comme vous ne pouvez pas Closeun DataReaderobjet nul , un tout nouveau NullReferenceExceptionrésultat.
Un Catchbloc vide est le terrain de jeu du diable. Cet OP était perplexe de savoir pourquoi il obtenait un NRE dans le Finallybloc. Dans d'autres situations, un vide Catchpeut entraîner quelque chose d'autre beaucoup plus en aval en se détraquant et vous faire passer du temps à regarder les mauvaises choses au mauvais endroit pour le problème. (L '"exception silencieuse" décrite ci-dessus offre la même valeur de divertissement.)
Remède
N'utilisez pas de blocs Try / Catch vides - laissez le code se bloquer afin que vous puissiez a) identifier la cause b) identifier l'emplacement et c) appliquer un remède approprié. Les blocs Try / Catch ne sont pas destinés à masquer les exceptions à la personne uniquement qualifiée pour les corriger - le développeur.
DBNull n'est pas la même chose que Nothing
ForEach row As DataGridViewRow In dgvPlanning.Rows
IfNot IsDBNull(row.Cells(0).Value)Then...
La IsDBNullfonction est utilisée pour tester si une valeur est égale à System.DBNull: De MSDN:
La valeur System.DBNull indique que l'objet représente des données manquantes ou inexistantes. DBNull n'est pas identique à Nothing, ce qui indique qu'une variable n'a pas encore été initialisée.
Remède
If row.Cells(0) IsNot NothingThen...
Comme précédemment, vous pouvez tester Rien, puis une valeur spécifique:
Dim getFoo =(From f In dbContext.FooBars
Where f.something = something
Select f).FirstOrDefault
IfNot IsDBNull(getFoo)ThenIf IsDBNull(getFoo.user_id)Then
txtFirst.Text = getFoo.first_name
Else...
FirstOrDefaultrenvoie le premier élément ou la valeur par défaut, qui est Nothingpour les types de référence et jamais DBNull:
If getFoo IsNot NothingThen...
Les contrôles
Dim chk As CheckBox
chk =CType(Me.Controls(chkName), CheckBox)If chk.Checked ThenReturn chk
EndIf
Si un CheckBoxavec chkNameest introuvable (ou existe dans un GroupBox), alors chksera Nothing et toute tentative de référence à une propriété entraînera une exception.
Si dgvBooksa AutoGenerateColumns = True, il va créer les colonnes, mais il ne les nomme pas, de sorte que le code ci - dessus échoue lorsqu'il y fait référence par son nom.
Remède
Nommez les colonnes manuellement ou référencez par index:
Lorsque votre DataGridViewa AllowUserToAddRowscomme Truevaleur par défaut, le Cellsdans la ligne vierge / nouvelle en bas contiendra tous Nothing. La plupart des tentatives d'utilisation du contenu (par exemple ToString) entraîneront un NRE.
Remède
Utilisez une For/Eachboucle et testez la IsNewRowpropriété pour déterminer s'il s'agit de cette dernière ligne. Cela fonctionne, que ce AllowUserToAddRowssoit vrai ou non:
ForEach r As DataGridViewRow in myDGV.Rows
If r.IsNewRow =FalseThen' ok to use this row
Si vous utilisez une For nboucle, modifier le nombre de lignes ou de l' utilisation Exit Forquand IsNewRowest vrai.
My.Settings (StringCollection)
Dans certaines circonstances, essayer d'utiliser un élément My.Settingsdont est un StringCollectionpeut entraîner une NullReference la première fois que vous l'utilisez. La solution est la même, mais pas aussi évidente. Considérer:
My.Settings.FooBars.Add("ziggy")' foobars is a string collection
Étant donné que VB gère les paramètres pour vous, il est raisonnable de s'attendre à ce qu'il initialise la collection. Il le sera, mais uniquement si vous avez précédemment ajouté une entrée initiale à la collection (dans l'éditeur de paramètres). Étant donné que la collection est (apparemment) initialisée lorsqu'un élément est ajouté, elle reste Nothinglorsqu'il n'y a aucun élément dans l'éditeur de paramètres à ajouter.
Remède
Initialisez la collection de paramètres dans le Loadgestionnaire d'événements du formulaire , si / quand nécessaire:
If My.Settings.FooBars IsNothingThen
My.Settings.FooBars =New System.Collections.Specialized.StringCollection
EndIf
En règle générale, la Settingscollection ne devra être initialisée que lors de la première exécution de l'application. Un autre remède consiste à ajouter une valeur initiale à votre collection dans Projet -> Paramètres | FooBars , enregistrez le projet, puis supprimez la fausse valeur.
Points clés
Vous avez probablement oublié l' Newopérateur.
ou
Quelque chose que vous supposiez fonctionnerait parfaitement pour retourner un objet initialisé à votre code, ne l'a pas fait.
N'ignorez (jamais) les avertissements du compilateur et utilisez Option Strict On(toujours).
Un autre scénario consiste à convertir un objet nul en un type de valeur . Par exemple, le code ci-dessous:
object o =null;DateTime d =(DateTime)o;
Il jettera un NullReferenceExceptionsur le casting. Cela semble assez évident dans l'exemple ci-dessus, mais cela peut se produire dans des scénarios complexes plus "à liaison tardive" où l'objet nul a été renvoyé à partir d'un code que vous ne possédez pas, et le transtypage est par exemple généré par un système automatique.
Un exemple de ceci est ce simple fragment de liaison ASP.NET avec le contrôle Calendar:
Ici, il SelectedDates'agit en fait d'une propriété - de DateTimetype - du Calendartype Contrôle Web, et la liaison pourrait parfaitement renvoyer quelque chose de nul. Le générateur implicite ASP.NET créera un morceau de code qui sera équivalent au code cast ci-dessus. Et cela soulèvera un NullReferenceExceptionproblème assez difficile à repérer, car il se trouve dans du code généré par ASP.NET qui compile très bien ...
Cela lèvera l'erreur parce que même si j'ai déclaré la variable " connection", elle n'est pointée vers rien. Lorsque j'essaie d'appeler le membre " Open", il n'y a aucune référence à résoudre et cela générera l'erreur.
Pour éviter cette erreur:
Initialisez toujours vos objets avant d'essayer de faire quoi que ce soit avec eux.
Si vous n'êtes pas sûr que l'objet soit nul, vérifiez-le avec object == null.
L'outil Resharper de JetBrains identifiera chaque endroit dans votre code qui a la possibilité d'une erreur de référence nulle, vous permettant de mettre une vérification nulle. Cette erreur est la première source de bogues, à mon humble avis.
L'outil Resharper de JetBrains identifiera chaque endroit dans votre code qui a la possibilité d'une erreur de référence nulle. Ceci est une erreur. J'ai une solution sans cette détection, mais le code résulte parfois à l'exception. Je soupçonne qu'il est parfois indétectable - du moins par eux - lorsque le multithreading est impliqué, mais je ne peux pas commenter davantage car je n'ai pas encore identifié l'emplacement de mon bogue.
j riv
Mais comment le résoudre lorsque l'exception NullReferenceException arrive en utilisant HttpContext.Current.Responce.Clear (). Il n'est résolu par aucune des solutions ci-dessus. car lors de la création de son objet objet de HttpContext, une erreur survient "La résolution de surcharge a échoué car aucun" Nouveau "accessible n'accepte ce nombre d'arguments.
Sunny Sandeep
158
Cela signifie que votre code a utilisé une variable de référence d'objet définie sur null (c'est-à-dire qu'il ne faisait pas référence à une instance d'objet réelle).
Pour éviter l'erreur, les objets qui pourraient être nuls doivent être testés pour null avant d'être utilisés.
if(myvar !=null){// Go ahead and use myvar
myvar.property=...}else{// Whoops! myvar is null and cannot be used without first// assigning it to an instance reference// Attempting to use myvar here will result in NullReferenceException}
Sachez que quel que soit le scénario, la cause est toujours la même dans .NET:
Vous essayez d'utiliser une variable de référence dont la valeur est Nothing/ null. Lorsque la valeur est Nothing/ nullpour la variable de référence, cela signifie qu'elle ne contient pas réellement de référence à une instance d'un objet qui existe sur le tas.
Soit vous n'avez jamais affecté quelque chose à la variable, vous n'avez jamais créé d'instance de la valeur affectée à la variable, soit vous définissez la variable égale à Nothing/ nullmanuellement, soit vous avez appelé une fonction qui définit la variable sur Nothing/ nullpour vous.
Un exemple de cette exception levée est: Lorsque vous essayez de vérifier quelque chose, c'est null.
Par exemple:
string testString =null;//Because it doesn't have a value (i.e. it's null; "Length" cannot do what it needs to do)if(testString.Length==0)// Throws a nullreferenceexception{//Do something}
Le runtime .NET lève une exception NullReferenceException lorsque vous essayez d'effectuer une action sur quelque chose qui n'a pas été instancié, c'est-à-dire le code ci-dessus.
Par rapport à une ArgumentNullException qui est généralement levée comme mesure défensive si une méthode s'attend à ce que ce qui lui est transmis ne soit pas nul.
C # 8.0 introduit des types de référence nullables et des types de référence non nullables . Par conséquent, seuls les types de référence nullables doivent être vérifiés pour éviter une exception NullReferenceException .
Si vous n'avez pas initialisé un type de référence et que vous souhaitez définir ou lire l'une de ses propriétés, il lèvera une exception NullReferenceException .
Exemple:
Person p =null;
p.Name="Harry";// NullReferenceException occurs here.
Vous pouvez simplement éviter cela en vérifiant si la variable n'est pas nulle:
Person p =null;if(p!=null){
p.Name="Harry";// Not going to run to this point}
Pour bien comprendre pourquoi une exception NullReferenceException est levée, il est important de connaître la différence entre les types de valeur et les [types de référence] [3].
Donc, si vous avez affaire à des types de valeur , NullReferenceExceptions ne peut pas se produire. Cependant, vous devez rester vigilant lorsque vous traitez avec des types de référence !
Seuls les types de référence, comme son nom l'indique, peuvent contenir des références ou pointer littéralement vers rien (ou «null»). Alors que les types de valeur contiennent toujours une valeur.
Types de référence (ceux-ci doivent être vérifiés):
dynamique
objet
chaîne
Types de valeurs (vous pouvez simplement ignorer ceux-ci):
-1: puisque la question est "Qu'est-ce qu'une exception NullReferenceException", les types de valeur ne sont pas pertinents.
John Saunders
21
@John Saunders: Je ne suis pas d'accord. En tant que développeur de logiciels, il est vraiment important de pouvoir distinguer les types de valeur et de référence. sinon les gens finiront par vérifier si les entiers sont nuls.
Fabian Bigler
5
C'est vrai, mais pas dans le contexte de cette question.
John Saunders
4
Merci pour l'astuce. Je l'ai un peu amélioré et j'ai ajouté un exemple en haut. Je pense toujours que mentionner les types de référence et de valeur est utile.
Fabian Bigler
5
Je pense que vous n'avez rien ajouté qui ne figurait pas dans les autres réponses, car la question présuppose un type de référence.
John Saunders
78
Un autre cas où NullReferenceExceptionscela peut se produire est l'utilisation (incorrecte) de l' asopérateur :
Ici, Booket Carsont des types incompatibles; a Carne peut pas être converti / converti en a Book. Lorsque cette conversion échoue, asrevient null. L'utilisation mybookaprès cela provoque a NullReferenceException.
En général, vous devez utiliser un cast ou as, comme suit:
Si vous vous attendez à ce que la conversion de type réussisse toujours (c'est-à-dire que vous savez ce que l'objet devrait être à l'avance), alors vous devez utiliser un transtypage:
ComicBook cb =(ComicBook)specificBook;
Si vous n'êtes pas sûr du type, mais que vous souhaitez essayer de l'utiliser comme type spécifique, utilisez as:
Cela peut se produire souvent lors du déballage d' une variable. Je trouve que cela se produit souvent dans les gestionnaires d'événements après avoir changé le type de l'élément d'interface utilisateur, mais oublie de mettre à jour le code-behind.
Brendan
65
Vous utilisez l'objet qui contient la référence de valeur nulle. Il s'agit donc de donner une exception nulle. Dans l'exemple, la valeur de chaîne est nulle et lors de la vérification de sa longueur, l'exception s'est produite.
Exemple:
stringvalue=null;if(value.Length==0)// <-- Causes exception{Console.WriteLine(value);// <-- Never reached}
L'erreur d'exception est:
Exception non-gérée:
System.NullReferenceException: référence d'objet non définie sur une instance d'un objet. à Program.Main ()
Quelle profondeur! Je n'ai jamais considéré la constante «nulle» comme une valeur de référence. C'est ainsi que C # résume un "NullPointer" hein? B / c si je me souviens en C ++, un NPE peut être provoqué en déréférençant un pointeur non initialisé (c'est-à-dire, ref type en c #) dont la valeur par défaut se trouve être une adresse qui n'est pas allouée à ce processus (dans de nombreux cas, ce serait 0, en particulier dans les versions ultérieures de C ++ qui ont fait l'auto-initialisation, qui appartient au système d'exploitation - f avec lui et mourir de beeotch (ou tout simplement attraper le sigkill avec lequel le système d'exploitation attaque votre processus)).
samis
64
Bien que ce qui provoque une NullReferenceExceptions et des approches pour éviter / corriger une telle exception ait été abordé dans d'autres réponses, ce que de nombreux programmeurs n'ont pas encore appris, c'est comment déboguer indépendamment ces exceptions pendant le développement.
À présent, lorsque l'exception NullReferenceException est levée (ou non gérée), le débogueur s'arrête (rappelez-vous la règle définie ci-dessus?) Sur la ligne sur laquelle l'exception s'est produite. Parfois, l'erreur sera facile à repérer.
Par exemple, dans la ligne suivante, le seul code qui peut provoquer l'exception est if myStrings'évalue à null. Cela peut être vérifié en regardant la fenêtre de surveillance ou en exécutant des expressions dans la fenêtre immédiate .
var x = myString.Trim();
Dans les cas plus avancés, tels que les suivants, vous devrez utiliser l'une des techniques ci-dessus (Windows Watch ou Immédiat) pour inspecter les expressions afin de déterminer si str1était nul ou str2non.
var x = str1.Trim()+ str2.Trim();
Une fois que l'exception a été repérée, il est généralement inutile de raisonner à l'envers pour savoir où la valeur nulle a été [incorrectement] introduite -
Prenez le temps nécessaire pour comprendre la cause de l'exception. Inspectez les expressions nulles. Inspectez les expressions précédentes qui auraient pu entraîner de telles expressions nulles. Ajoutez des points d'arrêt et parcourez le programme selon les besoins. Utilisez le débogueur.
1 Si Break on Throws est trop agressif et que le débogueur s'arrête sur un NPE dans la bibliothèque .NET ou tierce, Break on User-Unhandled peut être utilisé pour limiter les exceptions interceptées. De plus, VS2012 présente Just My Code que je recommande également d'activer.
Si vous déboguez avec Just My Code activé, le comportement est légèrement différent. Lorsque Just My Code est activé, le débogueur ignore les exceptions CLR (Common Language Runtime) de première chance qui sont levées en dehors de My Code et ne passent pas par My Code.
object o =null;DateTime d =(DateTime)o;// NullReferenceException
où une conversion unboxing (cast) deobject (ou de l'une des classes System.ValueTypeou System.Enum, ou d'un type d'interface) en un type de valeur (autre que Nullable<>) en soi donne le NullReferenceException.
Dans l'autre sens, une boxe conversion d' un Nullable<>qui a HasValueégal falseà un type de référence, peut donner une nullréférence qui peut alors conduire plus tard à un NullReferenceException. L'exemple classique est:
DateTime? d =null;var s = d.ToString();// OK, no exception (no boxing), returns ""var t = d.GetType();// Bang! d is boxed, NullReferenceException
Parfois, la boxe se déroule d'une autre manière. Par exemple avec cette méthode d'extension non générique:
Ajout d'un cas lorsque le nom de classe pour l'entité utilisée dans le cadre d'entité est identique au nom de classe pour un fichier code-behind de formulaire Web.
Supposons que vous ayez un formulaire Web Contact.aspx dont la classe codebehind est Contact et que vous ayez un nom d'entité Contact.
Ensuite, le code suivant lèvera une exception NullReferenceException lorsque vous appelez context.SaveChanges ()
Contact contact =newContact{Name="Abhinav"};var context =newDataContext();
context.Contacts.Add(contact);
context.SaveChanges();// NullReferenceException at this line
et Classe d'entité de contact. Parfois, les classes d'entités sont des classes partielles afin que vous puissiez également les étendre dans d'autres fichiers.
L'erreur se produit lorsque l'entité et la classe codebehind se trouvent dans le même espace de noms. Pour résoudre ce problème, renommez la classe d'entité ou la classe codebehind pour Contact.aspx.
Raison
Je ne suis toujours pas sûr de la raison. Mais chaque fois que l'une des classes d'entité étendra System.Web.UI.Page, cette erreur se produit.
Un autre cas général où l'on pourrait recevoir cette exception concerne les classes de simulation pendant les tests unitaires. Quel que soit le cadre de simulation utilisé, vous devez vous assurer que tous les niveaux appropriés de la hiérarchie des classes sont correctement simulés. En particulier, toutes les propriétés HttpContextréférencées par le code sous test doivent être moquées.
J'ai une perspective différente pour répondre à cela. Ce genre de réponses "que puis-je faire d'autre pour l'éviter? "
Lorsque vous travaillez sur différentes couches , par exemple dans une application MVC, un contrôleur a besoin de services pour appeler des opérations commerciales. Dans de tels scénarios, le conteneur d'injection de dépendances peut être utilisé pour initialiser les services afin d'éviter l' exception NullReferenceException . Cela signifie donc que vous n'avez pas à vous soucier de vérifier la valeur null et d'appeler simplement les services à partir du contrôleur comme s'ils seraient toujours disponibles (et initialisés) en tant que singleton ou prototype.
publicclassMyController{privateServiceA serviceA;privateServiceB serviceB;publicMyController(ServiceA serviceA,ServiceB serviceB){this.serviceA = serviceA;this.serviceB = serviceB;}publicvoidMyMethod(){// We don't need to check null because the dependency injection container // injects it, provided you took care of bootstrapping it.var someObject = serviceA.DoThis();}}
-1: cela ne gère qu'un seul scénario - celui des dépendances non initialisées. Il s'agit d'un scénario minoritaire pour NullReferenceException. La plupart des cas sont de simples malentendus sur le fonctionnement des objets. Viennent ensuite les autres situations où le développeur a supposé que l'objet serait initialisé automatiquement.
John Saunders
L'injection de dépendances n'est généralement pas utilisée afin d'éviter NullReferenceException. Je ne pense pas que vous ayez trouvé un scénario général ici. Dans tous les cas, si vous modifiez votre réponse pour être plus dans le style de stackoverflow.com/a/15232518/76337 , alors je supprimerai le downvote.
John Saunders
38
En ce qui concerne "que dois-je faire" , il peut y avoir de nombreuses réponses.
Une manière plus "formelle" d'empêcher de telles conditions d'erreur lors du développement consiste à appliquer la conception par contrat dans votre code. Cela signifie que vous devez définir des invariants de classe , et / ou même des préconditions et postconditions de fonction / méthode sur votre système, lors du développement.
En bref, les invariants de classe garantissent qu'il y aura des contraintes dans votre classe qui ne seront pas violées en utilisation normale (et par conséquent, la classe ne se mettra pas dans un état incohérent). Les conditions préalables signifient que les données fournies en entrée à une fonction / méthode doivent suivre un ensemble de contraintes et ne jamais les violer, et les post - conditions signifient qu'une sortie de fonction / méthode doit à nouveau suivre les contraintes définies sans jamais les violer. Les conditions du contrat ne doivent jamais être violées lors de l'exécution d'un programme sans bogue, donc la conception par contrat est vérifiée en pratique en mode débogage, tout en étant désactivée dans les versions , pour maximiser les performances du système développé.
De cette façon, vous pouvez éviter les NullReferenceExceptioncas qui résultent d'une violation de l'ensemble de contraintes. Par exemple, si vous utilisez une propriété d'objet Xdans une classe et essayez ultérieurement d'invoquer l'une de ses méthodes et Xque sa valeur est nulle, cela entraînera NullReferenceException:
public X {get;set;}publicvoidInvokeX(){
X.DoSomething();// if X value is null, you will get a NullReferenceException}
Mais si vous définissez «la propriété X ne doit jamais avoir de valeur nulle» comme condition préalable à la méthode, vous pouvez empêcher le scénario décrit précédemment:
//Using code contracts:[ContractInvariantMethod]protectedvoidObjectInvariant(){Contract.Invariant( X !=null);//...}
Pour cette raison, le projet Code Contracts existe pour les applications .NET.
Alternativement, la conception par contrat peut être appliquée à l'aide d' assertions .
J'ai pensé ajouter ceci car personne ne l'a mentionné, et dans la mesure où cela existe comme approche, mon intention était d'enrichir le sujet.
Nick Louloudakis
2
Merci d'avoir enrichi le sujet. J'ai donné mon avis sur votre ajout. Maintenant, d'autres peuvent faire de même.
John Saunders
2
J'ai pensé que c'était un ajout intéressant au sujet étant donné qu'il s'agit d'un fil très consulté. J'ai déjà entendu parler de contrats de code et c'était un bon rappel d'envisager de les utiliser.
VoteCoffee
36
Un NullReferenceExceptionest levé lorsque nous essayons d'accéder aux propriétés d'un objet nul ou lorsqu'une valeur de chaîne devient vide et que nous essayons d'accéder aux méthodes de chaîne.
Par exemple:
Lorsqu'une méthode de chaîne d'une chaîne vide accède:
Ceci est une erreur. String.Empty.ToLower()ne lèvera pas d'exception de référence nulle. Il représente une chaîne réelle, bien que vide (c'est-à-dire ""). Puisqu'il a un objet à appeler ToLower(), il ne serait pas logique d'y lancer une exception de référence nulle.
Kjartan du
31
TL; DR: essayez d'utiliser Html.Partialau lieu deRenderpage
J'obtenais Object reference not set to an instance of an objectquand j'ai essayé de rendre une vue dans une vue en lui envoyant un modèle, comme ceci:
@{MyEntity M =newMyEntity();}@RenderPage("_MyOtherView.cshtml", M);// error in _MyOtherView, the Model was Null
Le débogage a montré que le modèle était Null dans MyOtherView. Jusqu'à ce que je le change:
@{MyEntity M =newMyEntity();}@Html.Partial("_MyOtherView.cshtml", M);
Et ça a marché.
De plus, la raison pour laquelle je n'avais pas Html.Partialà commencer était parce que Visual Studio lançait parfois des lignes ondulées ressemblant à des erreurs Html.Partials'il se trouvait dans une foreachboucle de construction différente , même si ce n'est pas vraiment une erreur:
@inheritsSystem.Web.Mvc.WebViewPage@{ViewBag.Title="Entity Index";List<MyEntity>MyEntities=newList<MyEntity>();MyEntities.Add(newMyEntity());MyEntities.Add(newMyEntity());MyEntities.Add(newMyEntity());}<div>@{foreach(var M inMyEntities){// Squiggly lines below. Hovering says: cannot convert method group 'partial' to non-delegate type Object, did you intend to envoke the Method?@Html.Partial("MyOtherView.cshtml");}}</div>
Mais j'ai pu exécuter l'application sans problème avec cette "erreur". J'ai pu me débarrasser de l'erreur en modifiant la structure de la foreachboucle pour ressembler à ceci:
@foreach(var M inMyEntities){...}
Bien que j'ai le sentiment que c'était parce que Visual Studio lisait mal les esperluettes et les crochets.
Veuillez également indiquer quelle ligne a provoqué l'exception et pourquoi.
John Saunders
L'erreur s'est produite dans MyOtherView.cshtml, que je n'ai pas inclus ici, parce que le modèle n'était pas correctement envoyé (c'était le cas Null), donc je savais que l'erreur concernait la façon dont
j'envoyais
22
Que peux-tu y faire?
Il y a beaucoup de bonnes réponses ici expliquant ce qu'est une référence nulle et comment la déboguer. Mais il y a très peu de moyens de prévenir le problème ou du moins de le rendre plus facile à attraper.
Vérifier les arguments
Par exemple, les méthodes peuvent vérifier les différents arguments pour voir s'ils sont nuls et lever un ArgumentNullException, une exception évidemment créée dans ce but précis.
Le constructeur de ArgumentNullExceptioneven prend le nom du paramètre et un message comme arguments afin que vous puissiez dire exactement au développeur quel est le problème.
publicvoidDoSomething(MyObject obj){if(obj ==null){thrownewArgumentNullException("obj","Need a reference to obj.");}}
Utiliser des outils
Il existe également plusieurs bibliothèques qui peuvent vous aider. "Resharper" par exemple peut vous fournir des avertissements pendant que vous écrivez du code, surtout si vous utilisez leur attribut: NotNullAttribute
Il y a "Microsoft Code Contracts" où vous utilisez une syntaxe comme celle Contract.Requires(obj != null)qui vous donne l'exécution et la vérification de la compilation: Présentation de Code Contracts .
Il y a aussi "PostSharp" qui vous permettra d'utiliser simplement des attributs comme celui-ci:
publicvoidDoSometing([NotNull] obj)
En faisant cela et en faisant de PostSharp une partie de votre processus de construction, la valeur objnull sera vérifiée lors de l'exécution. Voir: PostSharp null check
Solution de code simple
Ou vous pouvez toujours coder votre propre approche en utilisant de l'ancien code. Par exemple, voici une structure que vous pouvez utiliser pour intercepter des références nulles. Il s'inspire du même concept que Nullable<T>:
[System.Diagnostics.DebuggerNonUserCode]publicstructNotNull<T>where T:class{private T _value;public T Value{get{if(_value ==null){thrownewException("null value not allowed");}return _value;}set{if(value==null){thrownewException("null value not allowed.");}
_value =value;}}publicstaticimplicitoperator T(NotNull<T> notNullValue){return notNullValue.Value;}publicstaticimplicitoperatorNotNull<T>(T value){returnnewNotNull<T>{Value=value};}}
Vous utiliseriez très similaire à la même manière que vous utiliseriez Nullable<T>, sauf dans le but d'accomplir exactement le contraire - de ne pas permettre null. Voici quelques exemples:
NotNull<Person> person =null;// throws exceptionNotNull<Person> person =newPerson();// OKNotNull<Person> person =GetPerson();// throws exception if GetPerson() returns null
NotNull<T>est implicitement casté vers et depuis Tafin que vous puissiez l'utiliser presque partout où vous en avez besoin. Par exemple, vous pouvez passer un Personobjet à une méthode qui prend NotNull<Person>:
Person person =newPerson{Name="John"};WriteName(person);publicstaticvoidWriteName(NotNull<Person> person){Console.WriteLine(person.Value.Name);}
Comme vous pouvez le voir ci-dessus, comme avec nullable, vous accéderez à la valeur sous-jacente via la Valuepropriété. Alternativement, vous pouvez utiliser une distribution explicite ou implicite, vous pouvez voir un exemple avec la valeur de retour ci-dessous:
Person person =GetPerson();publicstaticNotNull<Person>GetPerson(){returnnewPerson{Name="John"};}
Ou vous pouvez même l'utiliser lorsque la méthode revient T(dans ce cas Person) en faisant un cast. Par exemple, le code suivant aimerait juste le code ci-dessus:
Person person =(NotNull<Person>)GetPerson();publicstaticPersonGetPerson(){returnnewPerson{Name="John"};}
Combinez avec l'extension
Combinez NotNull<T>avec une méthode d'extension et vous pouvez couvrir encore plus de situations. Voici un exemple de ce à quoi peut ressembler la méthode d'extension:
[System.Diagnostics.DebuggerNonUserCode]publicstaticclassNotNullExtension{publicstatic T NotNull<T>(this T @this)where T:class{if(@this==null){thrownewException("null value not allowed");}return@this;}}
Et voici un exemple de la façon dont il pourrait être utilisé:
var person =GetPerson().NotNull();
GitHub
Pour votre référence, j'ai rendu le code ci-dessus disponible sur GitHub, vous pouvez le trouver sur:
C # 6.0 a introduit "l'opérateur null-conditionnel" qui aide un peu à cela. Avec cette fonctionnalité, vous pouvez référencer des objets imbriqués et si l'un d'eux est nulll'expression entière retourne null.
Cela réduit le nombre de contrôles nuls que vous devez effectuer dans certains cas. La syntaxe consiste à mettre un point d'interrogation avant chaque point. Prenons l'exemple du code suivant:
var address = country?.State?.County?.City;
Imaginez que countryc'est un objet de type Countryqui a une propriété appelée Stateet ainsi de suite. Si country, State, Countyou Cityest nullalors address will benulle . Therefore you only have to check whetheradresse isnull`.
C'est une excellente fonctionnalité, mais elle vous donne moins d'informations. Cela ne rend pas évident lequel des 4 est nul.
Intégré comme Nullable?
C # a un joli raccourci pour Nullable<T>, vous pouvez rendre quelque chose nullable en mettant un point d'interrogation après le type comme ça int?.
Ce serait bien si C # avait quelque chose comme le NotNull<T>struct ci - dessus et avait un raccourci similaire, peut - être le point d'exclamation pour que vous puissiez écrire quelque chose comme (!): public void WriteName(Person! person).
NullReferenceException est destiné à être levé par le CLR. Cela signifie qu'une référence à un null s'est produite. Cela ne signifie pas qu'une référence à un null se produirait, sauf que vous avez intelligemment vérifié en premier.
John Saunders
Je vois votre point sur la façon dont cela serait source de confusion. Je l'ai mis à jour vers une exception régulière pour cet exemple et une exception personnalisée dans GitHub.
Luis Perez
Excellente réponse à une question aussi simple. Ce n'est pas si mal quand c'est votre code qui échoue. C'est horrible quand cela vient du plus profond d'une bibliothèque commerciale tierce sur laquelle vous comptez, et le support client insiste pour que ce soit votre code qui cause le problème. Et vous n'êtes pas tout à fait sûr que ce n'est pas le cas et tout le projet doit s'arrêter. Je pense en fait que cela pourrait faire une épitaphe appropriée pour ma pierre tombale: "La référence d'objet n'est pas définie sur une instance d'un objet."
Darrel Lee
10
Fait intéressant, aucune des réponses sur cette page ne mentionne les deux cas de bord, j'espère que personne ne m'en voudra si je les ajoute:
Cas Edge # 1: accès simultané à un dictionnaire
Les dictionnaires génériques dans .NET ne sont pas adaptés aux threads et ils peuvent parfois générer un NullReferenceou même (plus fréquemment) un KeyNotFoundExceptionlorsque vous essayez d'accéder à une clé à partir de deux threads simultanés. L'exception est assez trompeuse dans ce cas.
Cas Edge # 2: code dangereux
Si un NullReferenceExceptionest généré par du unsafecode, vous pouvez regarder vos variables de pointeur et les vérifier IntPtr.Zeroou quelque chose. C'est la même chose ("exception de pointeur nul"), mais dans un code dangereux, les variables sont souvent transtypées en types de valeur / tableaux, etc., et vous vous cognez la tête contre le mur, en vous demandant comment un type de valeur peut jeter ceci exception.
(Une autre raison de ne pas utiliser de code dangereux, sauf si vous en avez besoin, en passant)
Votre exemple de dictionnaire n'est pas un cas de bord. Si l'objet n'est pas sûr pour les threads, son utilisation à partir de plusieurs threads produit des résultats aléatoires. Votre exemple de code dangereux diffère de nullquelle manière?
John Saunders
10
Vous pouvez corriger NullReferenceException de manière propre en utilisant des opérateurs Null-conditionnels en c # 6 et écrire moins de code pour gérer les vérifications nulles.
Il est utilisé pour tester null avant d'effectuer une opération d'accès aux membres (?.) Ou d'index (? [).
Exemple
var name = p?.Spouse?.FirstName;
est équivalent à:
if(p !=null){if(p.Spouse!=null){
name = p.Spouse.FirstName;}}
Le résultat est que le nom sera nul lorsque p est nul ou lorsque p.Spouse est nul.
Sinon, le nom de la variable se verra attribuer la valeur de p.Spouse.FirstName.
La ligne d'erreur "Référence d'objet non définie sur une instance d'un objet." Indique que vous n'avez pas affecté d'objet d'instance à une référence d'objet et que vous accédez toujours aux propriétés / méthodes de cet objet.
par exemple: disons que vous avez une classe appelée myClass et qu'elle contient une propriété prop1.
publicClass myClass
{publicint prop1 {get;set;}}
Maintenant, vous accédez à ce prop1 dans une autre classe comme ci-dessous:
publicclassDemo{publicvoid testMethod(){
myClass ref=null;ref.prop1 =1;//This line throws error}}
la ligne ci-dessus génère une erreur car la référence de la classe myClass est déclarée mais pas instanciée ou une instance d'objet n'est pas affectée à la référence de cette classe.
Pour résoudre ce problème, vous devez instancier (attribuer un objet à la référence de cette classe).
NullReferenceException ou Référence d'objet non définie sur une instance d'un objet se produit lorsqu'un objet de la classe que vous essayez d'utiliser n'est pas instancié. Par exemple:
Supposons que vous ayez une classe nommée Student.
Comme vu dans le code ci-dessus, l'instruction
Student s - déclare uniquement la variable de type Student, notez que la classe Student n'est pas instanciée à ce stade. Par conséquent, lorsque l'instruction s.GetFullName () est exécutée, elle lèvera l'exception NullReferenceException.
Vous essayez d'accéder à un objet qui n'est pas créé ou qui n'est pas actuellement en mémoire.
Alors, comment y faire face:
Déboguez et laissez le débogueur s'arrêter ... Cela vous amènera directement à la variable qui est cassée ... Maintenant, votre tâche est de simplement corriger cela .. En utilisant le nouveau mot-clé à l'endroit approprié.
Si cela est dû à certaines commandes de base de données parce que l'objet n'est pas présent, tout ce que vous avez à faire est de faire une vérification nulle et de le gérer:
if(i ==null){// Handle this}
Le plus difficile .. si le GC a déjà collecté l'objet ... Cela se produit généralement si vous essayez de trouver un objet à l'aide de chaînes ... Autrement dit, en le trouvant par le nom de l'objet, il peut arriver que le GC soit déjà nettoyé ... C'est difficile à trouver et deviendra un problème ... Une meilleure façon de résoudre ce problème est de faire des vérifications nulles partout où cela est nécessaire pendant le processus de développement. Cela vous fera gagner beaucoup de temps.
En recherchant par nom, je veux dire qu'un cadre vous permet de FIndObjects en utilisant des chaînes et le code pourrait ressembler à ceci: FindObject ("ObjectName");
Si vous avez une référence à un objet, le GC ne le nettoie jamais
John Saunders
2
si vous utilisez des choses comme FindObject ("Nom de l'objet") il n'y a aucun moyen que GC sache à l'avance que vous allez refernece cet objet .. c'est ce qui essayait d'expliquer .. cela se produit au moment de l'exécution
Akash Gutha
2
Il existe des cadres qui fournissent cette fonctionnalité en C # tels que Unity. la question n'a rien à voir avec BCl. Recherchez sur Internet avant de critiquer, il y a une tonne de fonctions comme elles et pour vos informations aimables, je les utilise même quotidiennement. Maintenant, dites-moi comment la réponse n'a aucun sens.
Les exemples que j'ai vus dans votre lien affectent les résultats de GameObject.Find à un champ membre. C'est une référence et le GC ne la collectera pas tant que l'objet contenant n'aura pas été collecté.
John Saunders
1
Littéralement, la façon la plus simple de corriger une NullReferenceExeption a deux façons. Si vous avez un GameObject par exemple avec un script attaché et une variable nommée rb (rigidbody), cette variable commencera nulle lorsque vous démarrez votre jeu.
C'est pourquoi vous obtenez une NullReferenceExeption car l'ordinateur n'a pas de données stockées dans cette variable.
Je vais utiliser une variable RigidBody comme exemple.
Nous pouvons ajouter des données très facilement de plusieurs manières:
Ajoutez un RigidBody à votre objet avec AddComponent> Physique> Rigidbody
Ensuite, allez dans votre script et tapez rb = GetComponent<Rigidbody>();
Cette ligne de code fonctionne mieux sous vos fonctions Start()ou Awake().
Vous pouvez ajouter un composant par programme et affecter la variable en même temps avec une ligne de code: rb = AddComponent<RigidBody>();
Notes supplémentaires: Si vous voulez que l'unité ajoute un composant à votre objet et que vous ayez oublié d'en ajouter un, vous pouvez taper [RequireComponent(typeof(RigidBody))]au-dessus de votre déclaration de classe (l'espace en dessous de tous vos usages).
Profitez et amusez-vous à créer des jeux!
Il s'agit essentiellement d'une exception de référence Null . Comme le déclare Microsoft-
Une exception NullReferenceException est levée lorsque vous essayez d'accéder à un membre d'un type dont la valeur est null.
Qu'est-ce que ça veut dire?
Cela signifie que si un membre qui n'a aucune valeur et que nous faisons en sorte que ce membre effectue certaines tâches, le système lancera sans aucun doute un message et dira -
"Hé, attendez, ce membre n'a aucune valeur, il ne peut donc pas exécuter la tâche que vous lui remettez."
L'exception elle-même dit que quelque chose est référé mais dont la valeur n'est pas définie. Cela signifie donc que cela se produit uniquement lors de l'utilisation de types de référence, car les types de valeur ne sont pas nullables.
NullReferenceException ne se produira pas si nous utilisons des membres de type Value.
Le code ci-dessus montre une chaîne simple qui est affectée d'un null valeur .
Maintenant, lorsque j'essaie d'imprimer la longueur de la chaîne str , j'obtiens une exception non gérée de type «System.NullReferenceException» , car le membre str pointe vers null et il ne peut pas y avoir de longueur nulle.
' NullReferenceException ' se produit également lorsque nous oublions d'instancier un type de référence.
Supposons que j'ai une classe et une méthode membre. Je n'ai pas instancié ma classe, mais seulement nommé ma classe. Maintenant, si j'essaie d'utiliser la méthode, le compilateur générera une erreur ou émettra un avertissement (selon le compilateur).
classProgram{staticvoidMain(string[] args){MyClass1 obj;
obj.foo();//Use of unassigned local variable 'obj'}}publicclassMyClass1{internalvoid foo(){Console.WriteLine("hello from foo");}}
Le compilateur pour le code ci-dessus génère une erreur indiquant que la variable obj n'est pas affectée, ce qui signifie que notre variable a des valeurs nulles ou rien. Le compilateur pour le code ci-dessus génère une erreur indiquant que la variable obj n'est pas affectée, ce qui signifie que notre variable a des valeurs nulles ou rien.
Pourquoi cela se produit-il?
NullReferenceException survient en raison de notre faute pour ne pas avoir vérifié la valeur de l'objet. Nous laissons souvent les valeurs des objets non contrôlées dans le développement du code.
Elle survient également lorsque nous oublions d'instancier nos objets. L'utilisation de méthodes, de propriétés, de collections, etc. qui peuvent renvoyer ou définir des valeurs nulles peut également être la cause de cette exception.
comment ca peut etre evite?
Il existe différentes façons et méthodes pour éviter cette exception renommée:
Vérification explicite: nous devons respecter la tradition de vérification des objets, propriétés, méthodes, tableaux et collections s'ils sont nuls. Cela peut être simplement implémenté en utilisant des instructions conditionnelles comme if-else if-else etc.
Gestion des exceptions: l'un des moyens importants de gérer cette exception. En utilisant de simples blocs try-catch-finally, nous pouvons contrôler cette exception et également en conserver un journal. Cela peut être très utile lorsque votre application est en phase de production.
Opérateurs nuls: L'opérateur nul coalescent et les opérateurs conditionnels nuls peuvent également être utilisés de manière pratique lors de la définition des valeurs des objets, des variables, des propriétés et des champs.
Débogueur: Pour les développeurs, nous avons la grande arme du débogage avec nous. Si nous rencontrons NullReferenceException pendant la phase de développement, nous pouvons utiliser le débogueur pour accéder à la source de l'exception.
Méthode intégrée: les méthodes système telles que GetValueOrDefault (), IsNullOrWhiteSpace () et IsNullorEmpty () vérifient les valeurs nulles et affectent la valeur par défaut s'il existe une valeur nulle.
Il y a déjà beaucoup de bonnes réponses ici. Vous pouvez également consulter une description plus détaillée avec des exemples sur mon blog .
Vous avez essentiellement copié la moitié de ce billet de blog et n'ajoutez rien de nouveau que les réponses existantes ne traitent pas.
CodeCaster
@codecaster Est-il dit de copier lorsque vous réécrivez un résumé de votre propre blog. Je sais qu'il n'y a rien de nouveau dans ma réponse et rien de nouveau que les réponses précédentes n'ont pas mais je souhaite apporter une contribution plus sophistiquée et laisser les autres comprendre la façon dont j'ai compris. Sera heureux même si cela aide une seule personne. De bonne foi.
Wasim
-4
Si l'on reçoit ce message lors de l'enregistrement ou de la compilation de la génération, fermez simplement tous les fichiers, puis ouvrez n'importe quel fichier à compiler et à enregistrer.
Pour moi, la raison était que j'avais renommé le fichier et que l'ancien fichier était toujours ouvert.
Réponses:
Quelle est la cause?
Bottom Line
Vous essayez d'utiliser quelque chose qui est
null
(ouNothing
dans VB.NET). Cela signifie que vous le définisseznull
ou que vous ne le définissez jamais du tout.Comme toute autre chose, se
null
fait passer. S'il se trouvenull
dans la méthode "A", il se peut que la méthode "B" soit passéenull
à la méthode "A".null
peut avoir différentes significations:NullReferenceException
.null
intentionnellement pour indiquer qu'aucune valeur significative n'est disponible. Notez que C # a le concept de types de données nullables pour les variables (comme les tables de base de données peuvent avoir des champs nullables) - vous pouvez leur affecternull
pour indiquer qu'il n'y a pas de valeur stockée dedans, par exempleint? a = null;
lorsque le point d'interrogation indique qu'il est autorisé à stocker null dans variablea
. Vous pouvez vérifier cela avecif (a.HasValue) {...}
ou avecif (a==null) {...}
. Les variables nulles, commea
cet exemple, permettent d'accéder à la valeur viaa.Value
explicitement, ou tout simplement via viaa
.Notez que y accéder via
a.Value
lance unInvalidOperationException
au lieu d'unNullReferenceException
ifa
estnull
- vous devez faire la vérification au préalable, c'est-à-dire que si vous avez une autre variable on-nullableint b;
alors vous devez faire des affectations commeif (a.HasValue) { b = a.Value; }
ou plus courtesif (a != null) { b = a; }
.Le reste de cet article va plus en détail et montre les erreurs que de nombreux programmeurs font souvent et qui peuvent conduire à un
NullReferenceException
.Plus précisement
Le
runtime
jetant unNullReferenceException
toujours signifie la même chose: vous essayez d'utiliser une référence, et la référence n'est pas initialisé (ou il a été une fois initialisé, mais il est plus initialisé).Cela signifie que la référence est
null
et que vous ne pouvez pas accéder aux membres (tels que les méthodes) via unenull
référence. Le cas le plus simple:Cela lancera un
NullReferenceException
à la deuxième ligne car vous ne pouvez pas appeler la méthode d'instanceToUpper()
sur unestring
référence pointant versnull
.Débogage
Comment trouvez-vous la source d'un
NullReferenceException
? En plus de regarder l'exception elle-même, qui sera levée exactement à l'endroit où elle se produit, les règles générales de débogage dans Visual Studio s'appliquent: placez des points d'arrêt stratégiques et inspectez vos variables , soit en passant la souris sur leurs noms, en ouvrant un ( Rapide) Regardez la fenêtre ou utilisez les divers panneaux de débogage comme les sections locales et les automobiles.Si vous souhaitez savoir où la référence est ou n'est pas définie, cliquez avec le bouton droit sur son nom et sélectionnez "Rechercher toutes les références". Vous pouvez ensuite placer un point d'arrêt à chaque emplacement trouvé et exécuter votre programme avec le débogueur attaché. Chaque fois que le débogueur s'arrête sur un tel point d'arrêt, vous devez déterminer si vous vous attendez à ce que la référence soit non nulle, inspecter la variable et vérifier qu'elle pointe vers une instance lorsque vous vous y attendez.
En suivant le flux du programme de cette façon, vous pouvez trouver l'emplacement où l'instance ne doit pas être nulle et pourquoi elle n'est pas correctement définie.
Exemples
Quelques scénarios courants où l'exception peut être levée:
Générique
Si ref1 ou ref2 ou ref3 est nul, vous obtiendrez a
NullReferenceException
. Si vous souhaitez résoudre le problème, recherchez celui qui est nul en réécrivant l'expression dans son équivalent le plus simple:Plus précisément, dans
HttpContext.Current.User.Identity.Name
, leHttpContext.Current
pourrait être nul, ou laUser
propriété pourrait être nulle, ou laIdentity
propriété pourrait être nulle.Indirect
Si vous souhaitez éviter la référence null enfant (Personne), vous pouvez l'initialiser dans le constructeur de l'objet parent (Livre).
Initialiseurs d'objets imbriqués
La même chose s'applique aux initialiseurs d'objets imbriqués:
Cela se traduit par
Pendant que le
new
mot-clé est utilisé, il crée seulement une nouvelle instance deBook
, mais pas une nouvelle instance dePerson
, doncAuthor
la propriété est toujoursnull
.Initialiseurs de collections imbriquées
La collection imbriquée
Initializers
se comporte de la même manière:Cela se traduit par
La
new Person
seule crée une instance dePerson
, mais laBooks
collection est toujoursnull
. LaInitializer
syntaxe de collection ne crée pas de collection pourp1.Books
, elle se traduit uniquement par lesp1.Books.Add(...)
instructions.Array
Éléments du tableau
Tableaux dentelés
Collection / Liste / Dictionnaire
Variable de plage (indirecte / différée)
Événements
classe publique Form1 {client Client privé;
}
Cela peut être résolu en suivant la convention pour préfixer les champs avec un trait de soulignement:
Cycle de vie de la page ASP.NET:
Valeurs de session ASP.NET
Modèles de vues vides ASP.NET MVC
Si l'exception se produit lors du référencement d'une propriété de
@Model
dans unASP.NET MVC View
, vous devez comprendre que leModel
get est défini dans votre méthode d'action, lorsque vousreturn
une vue. Lorsque vous renvoyez un modèle vide (ou une propriété de modèle) à partir de votre contrôleur, l'exception se produit lorsque les vues y accèdent:Ordre et événements de création de contrôle WPF
WPF
les contrôles sont créés lors de l'appel àInitializeComponent
dans l'ordre dans lequel ils apparaissent dans l'arborescence visuelle. UnNullReferenceException
sera soulevé dans le cas de contrôles créés au début avec des gestionnaires d'événements, etc., qui se déclenchent pendantInitializeComponent
lesquels référencent les contrôles créés tardivement.Par exemple :
Ici
comboBox1
est créé avantlabel1
. SicomboBox1_SelectionChanged
vous essayez de référencer `label1, il n'aura pas encore été créé.Changer l'ordre des déclarations dans le
XAML
(c.-à-d., Énumérerlabel1
avantcomboBox1
, ignorer les problèmes de philosophie de conception, résoudrait au moins l'NullReferenceException
ici.Cast avec
as
Cela ne lance pas un
InvalidCastException
mais renvoie unnull
lorsque le transtypage échoue (et quandsomeObject
est lui-même nul). Soyez donc conscient de cela.LINQ
FirstOrDefault()
etSingleOrDefault()
Les versions simples
First()
etSingle()
lèvent des exceptions quand il n'y a rien. Les versions "OrDefault" renvoient null dans ce cas. Soyez donc conscient de cela.pour chaque
foreach
jette lorsque vous essayez d'itérer la collection null. Habituellement provoqué par unnull
résultat inattendu des méthodes qui retournent des collections.Exemple plus réaliste - sélectionnez des nœuds dans un document XML. Jettera si les nœuds ne sont pas trouvés mais le débogage initial montre que toutes les propriétés valides:
Façons à éviter
Vérifiez
null
et ignorez explicitement les valeurs nulles.Si vous vous attendez à ce que la référence soit parfois nulle, vous pouvez vérifier qu'elle est
null
avant d'accéder aux membres de l'instance:Recherchez
null
et fournissez explicitement une valeur par défaut.Les méthodes que vous prévoyez de renvoyer peuvent renvoyer une instance
null
, par exemple lorsque l'objet recherché est introuvable. Vous pouvez choisir de renvoyer une valeur par défaut lorsque c'est le cas:Recherchez explicitement les
null
appels de méthode et lancez une exception personnalisée.Vous pouvez également lever une exception personnalisée, uniquement pour l'attraper dans le code appelant:
À utiliser
Debug.Assert
si une valeur ne doit jamais l'êtrenull
, pour détecter le problème avant que l'exception ne se produise.Lorsque vous savez pendant le développement qu'une méthode peut peut-être, mais ne devrait jamais revenir
null
, vous pouvez utiliserDebug.Assert()
pour interrompre dès que possible quand elle se produit:Bien que cette vérification ne se termine pas dans votre version , ce qui la fait lancer à
NullReferenceException
nouveau lorsbook == null
de l'exécution en mode de publication.Utilisez
GetValueOrDefault()
pour lesnullable
types de valeur pour fournir une valeur par défaut lorsqu'ils le sontnull
.Utilisez l'opérateur de coalescence nul:
??
[C #] ouIf()
[VB].Le raccourci pour fournir une valeur par défaut quand un
null
est rencontré:Utilisez l'opérateur de condition nulle:
?.
ou?[x]
pour les tableaux (disponibles en C # 6 et VB.NET 14):On l'appelle aussi parfois l'opérateur de navigation sécurisée ou Elvis (d'après sa forme). Si l'expression sur le côté gauche de l'opérateur est nulle, le côté droit ne sera pas évalué et null sera renvoyé à la place. Cela signifie des cas comme celui-ci:
Si la personne n'a pas de titre, cela lèvera une exception car elle essaie d'appeler
ToUpper
une propriété avec une valeur nulle.Dans
C# 5
et en dessous, cela peut être gardé avec:Maintenant, la variable de titre sera nulle au lieu de lever une exception. C # 6 introduit une syntaxe plus courte pour cela:
Cela se traduira par la variable de titre étant
null
, et l'appel àToUpper
n'est pas effectué siperson.Title
estnull
.Bien sûr, vous devez toujours vérifier
title
null ou utiliser l'opérateur de condition null avec l'opérateur de coalescence null (??
) pour fournir une valeur par défaut:De même, pour les tableaux, vous pouvez utiliser
?[i]
comme suit:Cela fera ce qui suit: Si
myIntArray
est null, l'expression renvoie null et vous pouvez le vérifier en toute sécurité. S'il contient un tableau, il fera la même chose que:elem = myIntArray[i];
et renvoie l'i<sup>th</sup>
élément.Utilisez un contexte nul (disponible en C # 8):
Introduits dans
C# 8
ce contexte, les types de contexte nullable et de référence nullable effectuent une analyse statique sur les variables et fournissent un avertissement du compilateur si une valeur peut être potentiellement nulle ou avoir été définie sur null. Les types de référence nullable permettent aux types d'être explicitement autorisés à être null.Le contexte d'annotation nullable et le contexte d'avertissement nullable peuvent être définis pour un projet à l'aide de l'
Nullable
élément dans votrecsproj
fichier. Cet élément configure la façon dont le compilateur interprète la nullité des types et quels avertissements sont générés. Les paramètres valides sont:Un type de référence nullable est noté en utilisant la même syntaxe que les types de valeur nullable: a
?
est ajouté au type de la variable.Techniques spéciales pour déboguer et corriger les derefs nuls dans les itérateurs
C#
prend en charge les "blocs d'itérateur" (appelés "générateurs" dans d'autres langues populaires). Les exceptions de déréférencement nul peuvent être particulièrement difficiles à déboguer dans les blocs d'itérateur en raison de l'exécution différée:Si les
whatever
résultats ennull
puisMakeFrob
jettera. Maintenant, vous pourriez penser que la bonne chose à faire est la suivante:Pourquoi est-ce mal? Parce que le bloc itérateur ne s'exécute pas tant que le
foreach
! L'appel àGetFrobs
renvoie simplement un objet qui, une fois itéré , exécutera le bloc itérateur.En écrivant une vérification nulle comme celle-ci, vous empêchez la déréférence nulle, mais vous déplacez l'exception d'argument nul au point de l' itération , pas au point de l' appel , ce qui est très déroutant pour le débogage .
La solution correcte est:
Autrement dit, créez une méthode d'assistance privée qui a la logique de blocage de l'itérateur et une méthode de surface publique qui effectue la vérification nulle et renvoie l'itérateur. Maintenant, quand
GetFrobs
est appelé, la vérification nulle se produit immédiatement, puisGetFrobsForReal
s'exécute lorsque la séquence est itérée.Si vous examinez la source de référence pour
LINQ
to Objects, vous verrez que cette technique est utilisée partout. Il est légèrement plus maladroit à écrire, mais il facilite beaucoup le débogage des erreurs de nullité. Optimisez votre code pour la commodité de l'appelant et non pour la commodité de l'auteur .Une note sur les déréférences nulles dans le code dangereux
C#
a un mode "dangereux" qui est, comme son nom l'indique, extrêmement dangereux car les mécanismes de sécurité normaux qui assurent la sécurité de la mémoire et la sécurité du type ne sont pas appliqués. Vous ne devez pas écrire de code dangereux à moins d'avoir une compréhension approfondie et approfondie du fonctionnement de la mémoire .En mode non sécurisé, vous devez être conscient de deux faits importants:
Pour comprendre pourquoi, il est utile de comprendre comment .NET produit en premier lieu des exceptions de déréférencement nul. (Ces détails s'appliquent à .NET exécuté sur Windows; d'autres systèmes d'exploitation utilisent des mécanismes similaires.)
La mémoire est virtualisée dans
Windows
; chaque processus obtient un espace de mémoire virtuelle de nombreuses "pages" de mémoire qui sont suivies par le système d'exploitation. Chaque page de mémoire comporte des indicateurs qui déterminent comment elle peut être utilisée: lecture, écriture, exécution, etc. La page la plus basse est marquée comme "produire une erreur si jamais utilisée de quelque façon que ce soit".Un pointeur nul et une référence nulle dans
C#
sont représentés en interne sous la forme du nombre zéro, et donc toute tentative de déréférencement dans son stockage mémoire correspondant entraîne une erreur du système d'exploitation. Le runtime .NET détecte ensuite cette erreur et la transforme en exception de déréférence nulle.C'est pourquoi le déréférencement d'un pointeur nul et d'une référence nulle produit la même exception.
Et le deuxième point? Le déréférencement de tout pointeur non valide qui tombe dans la page la plus basse de la mémoire virtuelle provoque la même erreur du système d'exploitation, et donc la même exception.
Pourquoi est-ce logique? Supposons que nous ayons une structure contenant deux entrées et un pointeur non géré égal à null. Si nous essayons de déréférencer le deuxième entier dans la structure, le
CLR
ne tentera pas d'accéder au stockage à l'emplacement zéro; il accédera au stockage à l'emplacement quatre. Mais logiquement, c'est une déréférence nulle parce que nous arrivons à cette adresse via la valeur nulle.Si vous travaillez avec du code dangereux et que vous obtenez une exception de déréférence nulle, sachez simplement que le pointeur incriminé n'a pas besoin d'être nul. Il peut s'agir de n'importe quel emplacement dans la page la plus basse et cette exception sera produite.
la source
new Book { Author = { Age = 45 } };
Comment l'initialisation interne fonctionne-t-elle même ... Je ne peux pas penser à une situation où l'init interne fonctionnerait jamais, mais il compile et l'intellisense fonctionne ... Sauf pour les structures?Exception NullReference - Visual Basic
Le
NullReference Exception
pour Visual Basic n'est pas différent de celui en C # . Après tout, ils signalent tous deux la même exception définie dans le .NET Framework qu'ils utilisent tous les deux. Les causes propres à Visual Basic sont rares (peut-être une seule).Cette réponse utilisera les termes, la syntaxe et le contexte Visual Basic. Les exemples utilisés proviennent d'un grand nombre de questions sur le débordement de pile passées. Il s'agit de maximiser la pertinence en utilisant les types de situations souvent vues dans les publications. Un peu plus d'explications sont également fournies pour ceux qui pourraient en avoir besoin. Un exemple similaire au vôtre est très probablement répertorié ici.
Remarque:
NullReferenceException
(NRE), comment le trouver, comment le réparer et comment l'éviter. Un NRE peut être causé de plusieurs façons, il est donc peu probable que ce soit votre seule rencontre.Signification de base
Le message "Objet non défini sur une instance d'Objet" signifie que vous essayez d'utiliser un objet qui n'a pas été initialisé. Cela se résume à l'un d'eux:
Trouver la cause
Puisque le problème est une référence d'objet qui est
Nothing
, la réponse est de les examiner pour trouver lequel. Déterminez ensuite pourquoi il n'est pas initialisé. Maintenez la souris sur les différentes variables et Visual Studio (VS) affichera leurs valeurs - le coupable seraNothing
.Vous devez également supprimer tous les blocs Try / Catch du code pertinent, en particulier ceux où il n'y a rien dans le bloc Catch. Cela provoquera le plantage de votre code lorsqu'il essaie d'utiliser un objet qui l'est
Nothing
. C'est ce que vous voulez car il identifiera l' emplacement exact du problème et vous permettra d'identifier l'objet à l'origine de ce problème.Un
MsgBox
in the Catch qui s'afficheError while...
ne sera d'aucune utilité. Cette méthode conduit également à de très mauvaises questions de débordement de pile, car vous ne pouvez pas décrire l'exception réelle, l'objet impliqué ou même la ligne de code où elle se produit.Vous pouvez également utiliser le
Locals Window
( Débogage -> Windows -> Locaux ) pour examiner vos objets.Une fois que vous savez quel est et où est le problème, il est généralement assez facile à résoudre et plus rapide que de poster une nouvelle question.
Voir également:
Exemples et remèdes
Objets de classe / Création d'une instance
Le problème est qu'il
Dim
ne crée pas d' objet CashRegister ; il déclare uniquement une variable nomméereg
de ce type. La déclaration d' une variable d'objet et la création d'une instance sont deux choses différentes.Remède
L'
New
opérateur peut souvent être utilisé pour créer l'instance lorsque vous la déclarez:Lorsqu'il ne convient que de créer l'instance ultérieurement:
Remarque: Ne réutilisez
Dim
pas dans une procédure, y compris le constructeur (Sub New
):Cela va créer une variable locale
reg
, qui n'existe que dans ce contexte (sub). Lareg
variable de niveau moduleScope
que vous utiliserez partout ailleurs resteNothing
.Pour être clair,
Dim
(ouPrivate
) ne déclare qu'une variable et sonType
. L' étendue de la variable - qu'elle existe pour l'ensemble du module / de la classe ou qu'elle soit locale à une procédure - est déterminée par l' endroit où elle est déclarée.Private | Friend | Public
définit le niveau d'accès, pas la portée .Pour plus d'informations, voir:
Tableaux
Les tableaux doivent également être instanciés:
Ce tableau a seulement été déclaré, pas créé. Il existe plusieurs façons d'initialiser un tableau:
Remarque: à partir de VS 2010, lors de l'initialisation d'un tableau local à l'aide d'un littéral et
Option Infer
, les élémentsAs <Type>
etNew
sont facultatifs:Le type de données et la taille du tableau sont déduits des données attribuées. Les déclarations de niveau de classe / module nécessitent toujours
As <Type>
avecOption Strict
:Exemple: tableau d'objets de classe
Le tableau a été créé, mais pas les
Foo
objets qu'il contient .Remède
Utiliser un
List(Of T)
rendra assez difficile d'avoir un élément sans objet valide:Pour plus d'informations, voir:
Listes et collections
Les collections .NET (dont il existe de nombreuses variétés - listes, dictionnaire, etc.) doivent également être instanciées ou créées.
Vous obtenez la même exception pour la même raison -
myList
n'a été déclaré, mais aucune instance n'a été créée. Le remède est le même:Un oubli commun est une classe qui utilise une collection
Type
:L'une ou l'autre procédure se traduira par un NRE, car il
barList
est uniquement déclaré, et non instancié. La création d'une instance deFoo
ne créera pas également une instance de l'internebarList
. C'était peut-être l'intention de le faire dans le constructeur:Comme précédemment, c'est incorrect:
Pour plus d'informations, voir
List(Of T)
Classe .Objets du fournisseur de données
Travailler avec des bases de données présente de nombreuses possibilités pour une NullReference car il peut y avoir de nombreux objets (
Command
,Connection
,Transaction
,Dataset
,DataTable
,DataRows
....) en usage à la fois. Remarque: Peu importe le fournisseur de données que vous utilisez - MySQL, SQL Server, OleDB, etc. - les concepts sont les mêmes.Exemple 1
Comme précédemment, l'
ds
objet Dataset a été déclaré, mais aucune instance n'a été créée. LeDataAdapter
remplira un existantDataSet
, pas en créer un. Dans ce cas, puisqu'ilds
s'agit d'une variable locale, l'EDI vous avertit que cela peut se produire:Lorsqu'il est déclaré en tant que variable de niveau module / classe, comme cela semble être le cas
con
, le compilateur ne peut pas savoir si l'objet a été créé par une procédure en amont. N'ignorez pas les avertissements.Remède
Exemple 2
Une faute de frappe est un problème ici:
Employees
vsEmployee
. AucunDataTable
"employé" n'a été créé, donc unNullReferenceException
résultat a tenté d'y accéder. Un autre problème potentiel est de supposer qu'il y en aura, ceItems
qui peut ne pas être le cas lorsque le SQL inclut une clause WHERE.Remède
Comme cela utilise une seule table, l'utilisation
Tables(0)
évitera les fautes d'orthographe. L'examenRows.Count
peut également aider:Fill
est une fonction renvoyant le nombre de personnesRows
affectées qui peut également être testée:Exemple 3
Le
DataAdapter
fourniraTableNames
comme indiqué dans l'exemple précédent, mais il n'analyse pas les noms de la table SQL ou de la base de données. Par conséquent,ds.Tables("TICKET_RESERVATION")
référence une table inexistante.Le remède est le même, référencez le tableau par index:
Voir aussi Classe DataTable .
Chemins d'objet / imbriqués
Le code ne teste
Items
que les deuxmyFoo
etBar
peut également être Nothing. Le remède consiste à tester la chaîne ou le chemin complet des objets un par un:AndAlso
est important. Les tests suivants ne seront pas effectués une fois la premièreFalse
condition rencontrée. Cela permet au code de «percer» en toute sécurité dans le (s) objet (s) un «niveau» à la fois, en évaluantmyFoo.Bar
uniquement après (et si)myFoo
est déterminé comme étant valide. Les chaînes ou chemins d'objets peuvent devenir assez longs lors du codage d'objets complexes:Il n'est pas possible de référencer quoi que ce soit «en aval» d'un
null
objet. Cela s'applique également aux contrôles:Ici,
myWebBrowser
ouDocument
pourrait être Nothing ou l'formfld1
élément peut ne pas exister.Contrôles de l'interface utilisateur
Entre autres choses, ce code ne prévoit pas que l'utilisateur n'a peut-être pas sélectionné quelque chose dans un ou plusieurs contrôles d'interface utilisateur.
ListBox1.SelectedItem
pourrait bien êtreNothing
, ilListBox1.SelectedItem.ToString
en résultera un NRE.Remède
Validez les données avant de les utiliser (utilisez également
Option Strict
les paramètres SQL et SQL):Vous pouvez également utiliser
(ComboBox5.SelectedItem IsNot Nothing) AndAlso...
Formulaires Visual Basic
Il s'agit d'un moyen assez courant d'obtenir un NRE. En C #, selon la façon dont il est codé, l'EDI signalera qu'il
Controls
n'existe pas dans le contexte actuel ou "ne peut pas référencer un membre non statique". Donc, dans une certaine mesure, c'est une situation uniquement VB. Il est également complexe car il peut entraîner une cascade de pannes.Les tableaux et les collections ne peuvent pas être initialisés de cette façon. Ce code d'initialisation s'exécutera avant que le constructeur ne crée le
Form
ou leControls
. Par conséquent:somevar
affectation entraînera un NRE immédiat car rien n'a de.Text
propriétéRéférencer les éléments du tableau ultérieurement entraînera un NRE. Si vous le faites dans
Form_Load
, en raison d'un bogue étrange, l'EDI peut ne pas signaler l'exception lorsqu'elle se produit. L'exception apparaîtra plus tard lorsque votre code essaie d'utiliser le tableau. Cette "exception silencieuse" est détaillée dans cet article . Pour nos besoins, la clé est que lorsque quelque chose de catastrophique se produit lors de la création d'un formulaire (Sub New
ou d'unForm Load
événement), les exceptions peuvent ne pas être signalées, le code quitte la procédure et affiche simplement le formulaire.Puisqu'aucun autre code dans votre événement
Sub New
ouForm Load
ne s'exécutera après le NRE, de nombreuses autres choses peuvent être laissées non initialisées.Notez que cela s'applique à toutes les références de contrôle et de composant qui les rendent illégales où elles se trouvent:
Remède partiel
Il est curieux que VB ne fournit pas un avertissement, mais le remède est de déclarer les conteneurs au niveau de la forme, mais initialiser les dans le gestionnaire d'événement de chargement de formulaire lorsque les contrôles font exist. Cela peut être fait
Sub New
tant que votre code est après l'InitializeComponent
appel:Le code du tableau n'est peut-être pas encore sorti du bois. Tous les contrôles qui sont dans un contrôle conteneur (comme un
GroupBox
ouPanel
) ne seront pas trouvés dansMe.Controls
; ils seront dans la collection Controls de ce Panel ou GroupBox. Un contrôle ne sera pas non plus renvoyé lorsque le nom du contrôle est mal orthographié ("TeStBox2"
). Dans de tels cas,Nothing
sera à nouveau stocké dans ces éléments du tableau et un NRE sera généré lorsque vous tenterez de le référencer.Ceux-ci devraient être faciles à trouver maintenant que vous savez ce que vous recherchez:
"Button2" réside sur un
Panel
Remède
Plutôt que des références indirectes par nom à l'aide de la
Controls
collection du formulaire , utilisez la référence de contrôle:Fonction ne retournant rien
Il s'agit d'un cas où l'EDI vous avertira que « tous les chemins ne renvoient pas une valeur et
NullReferenceException
peuvent en résulter ». Vous pouvez supprimer l'avertissement, en le remplaçantExit Function
parReturn Nothing
, mais cela ne résout pas le problème. Tout ce qui tente d'utiliser le retoursomeCondition = False
entraînera un NRE:Remède
Remplacez
Exit Function
la fonction parReturn bList
. Retourner un videList
n'est pas la même chose que retournerNothing
. S'il y a une chance qu'un objet retourné puisse l'êtreNothing
, testez avant de l'utiliser:Try / Catch mal implémenté
Un Try / Catch mal implémenté peut cacher où se trouve le problème et en entraîner de nouveaux:
Il s'agit d'un cas où un objet n'est pas créé comme prévu, mais démontre également la contre-utilité d'un vide
Catch
.Il y a une virgule supplémentaire dans le SQL (après 'mailaddress') qui entraîne une exception à
.ExecuteReader
. Après que leCatch
ne fait rien,Finally
essaie d'effectuer un nettoyage, mais comme vous ne pouvez pasClose
unDataReader
objet nul , un tout nouveauNullReferenceException
résultat.Un
Catch
bloc vide est le terrain de jeu du diable. Cet OP était perplexe de savoir pourquoi il obtenait un NRE dans leFinally
bloc. Dans d'autres situations, un videCatch
peut entraîner quelque chose d'autre beaucoup plus en aval en se détraquant et vous faire passer du temps à regarder les mauvaises choses au mauvais endroit pour le problème. (L '"exception silencieuse" décrite ci-dessus offre la même valeur de divertissement.)Remède
N'utilisez pas de blocs Try / Catch vides - laissez le code se bloquer afin que vous puissiez a) identifier la cause b) identifier l'emplacement et c) appliquer un remède approprié. Les blocs Try / Catch ne sont pas destinés à masquer les exceptions à la personne uniquement qualifiée pour les corriger - le développeur.
DBNull n'est pas la même chose que Nothing
La
IsDBNull
fonction est utilisée pour tester si une valeur est égale àSystem.DBNull
: De MSDN:Remède
Comme précédemment, vous pouvez tester Rien, puis une valeur spécifique:
Exemple 2
FirstOrDefault
renvoie le premier élément ou la valeur par défaut, qui estNothing
pour les types de référence et jamaisDBNull
:Les contrôles
Si un
CheckBox
avecchkName
est introuvable (ou existe dans unGroupBox
), alorschk
sera Nothing et toute tentative de référence à une propriété entraînera une exception.Remède
Le DataGridView
La DGV a quelques caprices vues périodiquement:
Si
dgvBooks
aAutoGenerateColumns = True
, il va créer les colonnes, mais il ne les nomme pas, de sorte que le code ci - dessus échoue lorsqu'il y fait référence par son nom.Remède
Nommez les colonnes manuellement ou référencez par index:
Exemple 2 - Méfiez-vous du NewRow
Lorsque votre
DataGridView
aAllowUserToAddRows
commeTrue
valeur par défaut, leCells
dans la ligne vierge / nouvelle en bas contiendra tousNothing
. La plupart des tentatives d'utilisation du contenu (par exempleToString
) entraîneront un NRE.Remède
Utilisez une
For/Each
boucle et testez laIsNewRow
propriété pour déterminer s'il s'agit de cette dernière ligne. Cela fonctionne, que ceAllowUserToAddRows
soit vrai ou non:Si vous utilisez une
For n
boucle, modifier le nombre de lignes ou de l' utilisationExit For
quandIsNewRow
est vrai.My.Settings (StringCollection)
Dans certaines circonstances, essayer d'utiliser un élément
My.Settings
dont est unStringCollection
peut entraîner une NullReference la première fois que vous l'utilisez. La solution est la même, mais pas aussi évidente. Considérer:Étant donné que VB gère les paramètres pour vous, il est raisonnable de s'attendre à ce qu'il initialise la collection. Il le sera, mais uniquement si vous avez précédemment ajouté une entrée initiale à la collection (dans l'éditeur de paramètres). Étant donné que la collection est (apparemment) initialisée lorsqu'un élément est ajouté, elle reste
Nothing
lorsqu'il n'y a aucun élément dans l'éditeur de paramètres à ajouter.Remède
Initialisez la collection de paramètres dans le
Load
gestionnaire d'événements du formulaire , si / quand nécessaire:En règle générale, la
Settings
collection ne devra être initialisée que lors de la première exécution de l'application. Un autre remède consiste à ajouter une valeur initiale à votre collection dans Projet -> Paramètres | FooBars , enregistrez le projet, puis supprimez la fausse valeur.Points clés
Vous avez probablement oublié l'
New
opérateur.ou
Quelque chose que vous supposiez fonctionnerait parfaitement pour retourner un objet initialisé à votre code, ne l'a pas fait.
N'ignorez (jamais) les avertissements du compilateur et utilisez
Option Strict On
(toujours).Exception MSDN NullReference
la source
Un autre scénario consiste à convertir un objet nul en un type de valeur . Par exemple, le code ci-dessous:
Il jettera un
NullReferenceException
sur le casting. Cela semble assez évident dans l'exemple ci-dessus, mais cela peut se produire dans des scénarios complexes plus "à liaison tardive" où l'objet nul a été renvoyé à partir d'un code que vous ne possédez pas, et le transtypage est par exemple généré par un système automatique.Un exemple de ceci est ce simple fragment de liaison ASP.NET avec le contrôle Calendar:
Ici, il
SelectedDate
s'agit en fait d'une propriété - deDateTime
type - duCalendar
type Contrôle Web, et la liaison pourrait parfaitement renvoyer quelque chose de nul. Le générateur implicite ASP.NET créera un morceau de code qui sera équivalent au code cast ci-dessus. Et cela soulèvera unNullReferenceException
problème assez difficile à repérer, car il se trouve dans du code généré par ASP.NET qui compile très bien ...la source
DateTime x = (DateTime) o as DateTime? ?? defaultValue;
Cela signifie que la variable en question ne pointe vers rien. Je pourrais générer ceci comme ceci:
Cela lèvera l'erreur parce que même si j'ai déclaré la variable "
connection
", elle n'est pointée vers rien. Lorsque j'essaie d'appeler le membre "Open
", il n'y a aucune référence à résoudre et cela générera l'erreur.Pour éviter cette erreur:
object == null
.L'outil Resharper de JetBrains identifiera chaque endroit dans votre code qui a la possibilité d'une erreur de référence nulle, vous permettant de mettre une vérification nulle. Cette erreur est la première source de bogues, à mon humble avis.
la source
Cela signifie que votre code a utilisé une variable de référence d'objet définie sur null (c'est-à-dire qu'il ne faisait pas référence à une instance d'objet réelle).
Pour éviter l'erreur, les objets qui pourraient être nuls doivent être testés pour null avant d'être utilisés.
la source
Sachez que quel que soit le scénario, la cause est toujours la même dans .NET:
la source
Un exemple de cette exception levée est: Lorsque vous essayez de vérifier quelque chose, c'est null.
Par exemple:
Le runtime .NET lève une exception NullReferenceException lorsque vous essayez d'effectuer une action sur quelque chose qui n'a pas été instancié, c'est-à-dire le code ci-dessus.
Par rapport à une ArgumentNullException qui est généralement levée comme mesure défensive si une méthode s'attend à ce que ce qui lui est transmis ne soit pas nul.
Plus d'informations sont dans C # NullReferenceException et Null Parameter .
la source
Mise à jour C # 8.0, 2019: types de référence nullables
C # 8.0 introduit des types de référence nullables et des types de référence non nullables . Par conséquent, seuls les types de référence nullables doivent être vérifiés pour éviter une exception NullReferenceException .
Si vous n'avez pas initialisé un type de référence et que vous souhaitez définir ou lire l'une de ses propriétés, il lèvera une exception NullReferenceException .
Exemple:
Vous pouvez simplement éviter cela en vérifiant si la variable n'est pas nulle:
Pour bien comprendre pourquoi une exception NullReferenceException est levée, il est important de connaître la différence entre les types de valeur et les [types de référence] [3].
Donc, si vous avez affaire à des types de valeur , NullReferenceExceptions ne peut pas se produire. Cependant, vous devez rester vigilant lorsque vous traitez avec des types de référence !
Seuls les types de référence, comme son nom l'indique, peuvent contenir des références ou pointer littéralement vers rien (ou «null»). Alors que les types de valeur contiennent toujours une valeur.
Types de référence (ceux-ci doivent être vérifiés):
Types de valeurs (vous pouvez simplement ignorer ceux-ci):
la source
Un autre cas où
NullReferenceExceptions
cela peut se produire est l'utilisation (incorrecte) de l'as
opérateur :Ici,
Book
etCar
sont des types incompatibles; aCar
ne peut pas être converti / converti en aBook
. Lorsque cette conversion échoue,as
revientnull
. L'utilisationmybook
après cela provoque aNullReferenceException
.En général, vous devez utiliser un cast ou
as
, comme suit:Si vous vous attendez à ce que la conversion de type réussisse toujours (c'est-à-dire que vous savez ce que l'objet devrait être à l'avance), alors vous devez utiliser un transtypage:
Si vous n'êtes pas sûr du type, mais que vous souhaitez essayer de l'utiliser comme type spécifique, utilisez
as
:la source
Vous utilisez l'objet qui contient la référence de valeur nulle. Il s'agit donc de donner une exception nulle. Dans l'exemple, la valeur de chaîne est nulle et lors de la vérification de sa longueur, l'exception s'est produite.
Exemple:
L'erreur d'exception est:
la source
Bien que ce qui provoque une NullReferenceExceptions et des approches pour éviter / corriger une telle exception ait été abordé dans d'autres réponses, ce que de nombreux programmeurs n'ont pas encore appris, c'est comment déboguer indépendamment ces exceptions pendant le développement.
Dans Visual Studio, cela est généralement facile grâce au débogueur Visual Studio .
Tout d'abord, assurez-vous que l'erreur correcte sera détectée - voir Comment puis-je autoriser la rupture sur 'System.NullReferenceException' dans VS2010? Remarque 1
Ensuite, commencez avec le débogage (F5) ou attachez [le débogueur VS] au processus en cours d'exécution . À l'occasion, il peut être utile de l'utiliser
Debugger.Break
, ce qui vous demandera de lancer le débogueur.À présent, lorsque l'exception NullReferenceException est levée (ou non gérée), le débogueur s'arrête (rappelez-vous la règle définie ci-dessus?) Sur la ligne sur laquelle l'exception s'est produite. Parfois, l'erreur sera facile à repérer.
Par exemple, dans la ligne suivante, le seul code qui peut provoquer l'exception est if
myString
s'évalue à null. Cela peut être vérifié en regardant la fenêtre de surveillance ou en exécutant des expressions dans la fenêtre immédiate .Dans les cas plus avancés, tels que les suivants, vous devrez utiliser l'une des techniques ci-dessus (Windows Watch ou Immédiat) pour inspecter les expressions afin de déterminer si
str1
était nul oustr2
non.Une fois que l'exception a été repérée, il est généralement inutile de raisonner à l'envers pour savoir où la valeur nulle a été [incorrectement] introduite -
Prenez le temps nécessaire pour comprendre la cause de l'exception. Inspectez les expressions nulles. Inspectez les expressions précédentes qui auraient pu entraîner de telles expressions nulles. Ajoutez des points d'arrêt et parcourez le programme selon les besoins. Utilisez le débogueur.
1 Si Break on Throws est trop agressif et que le débogueur s'arrête sur un NPE dans la bibliothèque .NET ou tierce, Break on User-Unhandled peut être utilisé pour limiter les exceptions interceptées. De plus, VS2012 présente Just My Code que je recommande également d'activer.
la source
Simon Mourier a donné cet exemple :
où une conversion unboxing (cast) de
object
(ou de l'une des classesSystem.ValueType
ouSystem.Enum
, ou d'un type d'interface) en un type de valeur (autre queNullable<>
) en soi donne leNullReferenceException
.Dans l'autre sens, une boxe conversion d' un
Nullable<>
qui aHasValue
égalfalse
à un type de référence, peut donner unenull
référence qui peut alors conduire plus tard à unNullReferenceException
. L'exemple classique est:Parfois, la boxe se déroule d'une autre manière. Par exemple avec cette méthode d'extension non générique:
le code suivant sera problématique:
Ces cas surviennent en raison des règles spéciales que le runtime utilise lors de la boxe des
Nullable<>
instances.la source
Ajout d'un cas lorsque le nom de classe pour l'entité utilisée dans le cadre d'entité est identique au nom de classe pour un fichier code-behind de formulaire Web.
Supposons que vous ayez un formulaire Web Contact.aspx dont la classe codebehind est Contact et que vous ayez un nom d'entité Contact.
Ensuite, le code suivant lèvera une exception NullReferenceException lorsque vous appelez context.SaveChanges ()
Par souci d'exhaustivité, classe DataContext
et Classe d'entité de contact. Parfois, les classes d'entités sont des classes partielles afin que vous puissiez également les étendre dans d'autres fichiers.
L'erreur se produit lorsque l'entité et la classe codebehind se trouvent dans le même espace de noms. Pour résoudre ce problème, renommez la classe d'entité ou la classe codebehind pour Contact.aspx.
Raison Je ne suis toujours pas sûr de la raison. Mais chaque fois que l'une des classes d'entité étendra System.Web.UI.Page, cette erreur se produit.
Pour la discussion, jetez un œil à NullReferenceException dans DbContext.saveChanges ()
la source
Un autre cas général où l'on pourrait recevoir cette exception concerne les classes de simulation pendant les tests unitaires. Quel que soit le cadre de simulation utilisé, vous devez vous assurer que tous les niveaux appropriés de la hiérarchie des classes sont correctement simulés. En particulier, toutes les propriétés
HttpContext
référencées par le code sous test doivent être moquées.Voir « NullReferenceException levée lors du test de AuthorizationAttribute personnalisé » pour un exemple quelque peu détaillé.
la source
J'ai une perspective différente pour répondre à cela. Ce genre de réponses "que puis-je faire d'autre pour l'éviter? "
Lorsque vous travaillez sur différentes couches , par exemple dans une application MVC, un contrôleur a besoin de services pour appeler des opérations commerciales. Dans de tels scénarios, le conteneur d'injection de dépendances peut être utilisé pour initialiser les services afin d'éviter l' exception NullReferenceException . Cela signifie donc que vous n'avez pas à vous soucier de vérifier la valeur null et d'appeler simplement les services à partir du contrôleur comme s'ils seraient toujours disponibles (et initialisés) en tant que singleton ou prototype.
la source
En ce qui concerne "que dois-je faire" , il peut y avoir de nombreuses réponses.
Une manière plus "formelle" d'empêcher de telles conditions d'erreur lors du développement consiste à appliquer la conception par contrat dans votre code. Cela signifie que vous devez définir des invariants de classe , et / ou même des préconditions et postconditions de fonction / méthode sur votre système, lors du développement.
En bref, les invariants de classe garantissent qu'il y aura des contraintes dans votre classe qui ne seront pas violées en utilisation normale (et par conséquent, la classe ne se mettra pas dans un état incohérent). Les conditions préalables signifient que les données fournies en entrée à une fonction / méthode doivent suivre un ensemble de contraintes et ne jamais les violer, et les post - conditions signifient qu'une sortie de fonction / méthode doit à nouveau suivre les contraintes définies sans jamais les violer. Les conditions du contrat ne doivent jamais être violées lors de l'exécution d'un programme sans bogue, donc la conception par contrat est vérifiée en pratique en mode débogage, tout en étant désactivée dans les versions , pour maximiser les performances du système développé.
De cette façon, vous pouvez éviter les
NullReferenceException
cas qui résultent d'une violation de l'ensemble de contraintes. Par exemple, si vous utilisez une propriété d'objetX
dans une classe et essayez ultérieurement d'invoquer l'une de ses méthodes etX
que sa valeur est nulle, cela entraîneraNullReferenceException
:Mais si vous définissez «la propriété X ne doit jamais avoir de valeur nulle» comme condition préalable à la méthode, vous pouvez empêcher le scénario décrit précédemment:
Pour cette raison, le projet Code Contracts existe pour les applications .NET.
Alternativement, la conception par contrat peut être appliquée à l'aide d' assertions .
MISE À JOUR: Il convient de mentionner que le terme a été inventé par Bertrand Meyer dans le cadre de sa conception du langage de programmation Eiffel .
la source
Un
NullReferenceException
est levé lorsque nous essayons d'accéder aux propriétés d'un objet nul ou lorsqu'une valeur de chaîne devient vide et que nous essayons d'accéder aux méthodes de chaîne.Par exemple:
Lorsqu'une méthode de chaîne d'une chaîne vide accède:
Lorsqu'une propriété d'un objet nul accède:
la source
String.Empty.ToLower()
ne lèvera pas d'exception de référence nulle. Il représente une chaîne réelle, bien que vide (c'est-à-dire""
). Puisqu'il a un objet à appelerToLower()
, il ne serait pas logique d'y lancer une exception de référence nulle.TL; DR: essayez d'utiliser
Html.Partial
au lieu deRenderpage
J'obtenais
Object reference not set to an instance of an object
quand j'ai essayé de rendre une vue dans une vue en lui envoyant un modèle, comme ceci:Le débogage a montré que le modèle était Null dans MyOtherView. Jusqu'à ce que je le change:
Et ça a marché.
De plus, la raison pour laquelle je n'avais pas
Html.Partial
à commencer était parce que Visual Studio lançait parfois des lignes ondulées ressemblant à des erreursHtml.Partial
s'il se trouvait dans uneforeach
boucle de construction différente , même si ce n'est pas vraiment une erreur:Mais j'ai pu exécuter l'application sans problème avec cette "erreur". J'ai pu me débarrasser de l'erreur en modifiant la structure de la
foreach
boucle pour ressembler à ceci:Bien que j'ai le sentiment que c'était parce que Visual Studio lisait mal les esperluettes et les crochets.
la source
Html.Partial
, pas@Html.Partial
Null
), donc je savais que l'erreur concernait la façon dontQue peux-tu y faire?
Il y a beaucoup de bonnes réponses ici expliquant ce qu'est une référence nulle et comment la déboguer. Mais il y a très peu de moyens de prévenir le problème ou du moins de le rendre plus facile à attraper.
Vérifier les arguments
Par exemple, les méthodes peuvent vérifier les différents arguments pour voir s'ils sont nuls et lever un
ArgumentNullException
, une exception évidemment créée dans ce but précis.Le constructeur de
ArgumentNullException
even prend le nom du paramètre et un message comme arguments afin que vous puissiez dire exactement au développeur quel est le problème.Utiliser des outils
Il existe également plusieurs bibliothèques qui peuvent vous aider. "Resharper" par exemple peut vous fournir des avertissements pendant que vous écrivez du code, surtout si vous utilisez leur attribut: NotNullAttribute
Il y a "Microsoft Code Contracts" où vous utilisez une syntaxe comme celle
Contract.Requires(obj != null)
qui vous donne l'exécution et la vérification de la compilation: Présentation de Code Contracts .Il y a aussi "PostSharp" qui vous permettra d'utiliser simplement des attributs comme celui-ci:
En faisant cela et en faisant de PostSharp une partie de votre processus de construction, la valeur
obj
null sera vérifiée lors de l'exécution. Voir: PostSharp null checkSolution de code simple
Ou vous pouvez toujours coder votre propre approche en utilisant de l'ancien code. Par exemple, voici une structure que vous pouvez utiliser pour intercepter des références nulles. Il s'inspire du même concept que
Nullable<T>
:Vous utiliseriez très similaire à la même manière que vous utiliseriez
Nullable<T>
, sauf dans le but d'accomplir exactement le contraire - de ne pas permettrenull
. Voici quelques exemples:NotNull<T>
est implicitement casté vers et depuisT
afin que vous puissiez l'utiliser presque partout où vous en avez besoin. Par exemple, vous pouvez passer unPerson
objet à une méthode qui prendNotNull<Person>
:Comme vous pouvez le voir ci-dessus, comme avec nullable, vous accéderez à la valeur sous-jacente via la
Value
propriété. Alternativement, vous pouvez utiliser une distribution explicite ou implicite, vous pouvez voir un exemple avec la valeur de retour ci-dessous:Ou vous pouvez même l'utiliser lorsque la méthode revient
T
(dans ce casPerson
) en faisant un cast. Par exemple, le code suivant aimerait juste le code ci-dessus:Combinez avec l'extension
Combinez
NotNull<T>
avec une méthode d'extension et vous pouvez couvrir encore plus de situations. Voici un exemple de ce à quoi peut ressembler la méthode d'extension:Et voici un exemple de la façon dont il pourrait être utilisé:
GitHub
Pour votre référence, j'ai rendu le code ci-dessus disponible sur GitHub, vous pouvez le trouver sur:
https://github.com/luisperezphd/NotNull
Fonction de langue associée
C # 6.0 a introduit "l'opérateur null-conditionnel" qui aide un peu à cela. Avec cette fonctionnalité, vous pouvez référencer des objets imbriqués et si l'un d'eux est
null
l'expression entière retournenull
.Cela réduit le nombre de contrôles nuls que vous devez effectuer dans certains cas. La syntaxe consiste à mettre un point d'interrogation avant chaque point. Prenons l'exemple du code suivant:
Imaginez que
country
c'est un objet de typeCountry
qui a une propriété appeléeState
et ainsi de suite. Sicountry
,State
,County
ouCity
estnull
alorsaddress will be
nulle. Therefore you only have to check whether
adresseis
null`.C'est une excellente fonctionnalité, mais elle vous donne moins d'informations. Cela ne rend pas évident lequel des 4 est nul.
Intégré comme Nullable?
C # a un joli raccourci pour
Nullable<T>
, vous pouvez rendre quelque chose nullable en mettant un point d'interrogation après le type comme çaint?
.Ce serait bien si C # avait quelque chose comme le
NotNull<T>
struct ci - dessus et avait un raccourci similaire, peut - être le point d'exclamation pour que vous puissiez écrire quelque chose comme (!):public void WriteName(Person! person)
.la source
Fait intéressant, aucune des réponses sur cette page ne mentionne les deux cas de bord, j'espère que personne ne m'en voudra si je les ajoute:
Cas Edge # 1: accès simultané à un dictionnaire
Les dictionnaires génériques dans .NET ne sont pas adaptés aux threads et ils peuvent parfois générer un
NullReference
ou même (plus fréquemment) unKeyNotFoundException
lorsque vous essayez d'accéder à une clé à partir de deux threads simultanés. L'exception est assez trompeuse dans ce cas.Cas Edge # 2: code dangereux
Si un
NullReferenceException
est généré par duunsafe
code, vous pouvez regarder vos variables de pointeur et les vérifierIntPtr.Zero
ou quelque chose. C'est la même chose ("exception de pointeur nul"), mais dans un code dangereux, les variables sont souvent transtypées en types de valeur / tableaux, etc., et vous vous cognez la tête contre le mur, en vous demandant comment un type de valeur peut jeter ceci exception.(Une autre raison de ne pas utiliser de code dangereux, sauf si vous en avez besoin, en passant)
la source
null
quelle manière?Vous pouvez corriger NullReferenceException de manière propre en utilisant des opérateurs Null-conditionnels en c # 6 et écrire moins de code pour gérer les vérifications nulles.
Il est utilisé pour tester null avant d'effectuer une opération d'accès aux membres (?.) Ou d'index (? [).
Exemple
est équivalent à:
Le résultat est que le nom sera nul lorsque p est nul ou lorsque p.Spouse est nul.
Sinon, le nom de la variable se verra attribuer la valeur de p.Spouse.FirstName.
Pour plus de détails: opérateurs null-conditionnels
la source
La ligne d'erreur "Référence d'objet non définie sur une instance d'un objet." Indique que vous n'avez pas affecté d'objet d'instance à une référence d'objet et que vous accédez toujours aux propriétés / méthodes de cet objet.
par exemple: disons que vous avez une classe appelée myClass et qu'elle contient une propriété prop1.
Maintenant, vous accédez à ce prop1 dans une autre classe comme ci-dessous:
la ligne ci-dessus génère une erreur car la référence de la classe myClass est déclarée mais pas instanciée ou une instance d'objet n'est pas affectée à la référence de cette classe.
Pour résoudre ce problème, vous devez instancier (attribuer un objet à la référence de cette classe).
la source
NullReferenceException ou Référence d'objet non définie sur une instance d'un objet se produit lorsqu'un objet de la classe que vous essayez d'utiliser n'est pas instancié. Par exemple:
Supposons que vous ayez une classe nommée Student.
Maintenant, considérez une autre classe où vous essayez de récupérer le nom complet de l'élève.
Comme vu dans le code ci-dessus, l'instruction Student s - déclare uniquement la variable de type Student, notez que la classe Student n'est pas instanciée à ce stade. Par conséquent, lorsque l'instruction s.GetFullName () est exécutée, elle lèvera l'exception NullReferenceException.
la source
Eh bien, en termes simples:
Vous essayez d'accéder à un objet qui n'est pas créé ou qui n'est pas actuellement en mémoire.
Alors, comment y faire face:
Déboguez et laissez le débogueur s'arrêter ... Cela vous amènera directement à la variable qui est cassée ... Maintenant, votre tâche est de simplement corriger cela .. En utilisant le nouveau mot-clé à l'endroit approprié.
Si cela est dû à certaines commandes de base de données parce que l'objet n'est pas présent, tout ce que vous avez à faire est de faire une vérification nulle et de le gérer:
Le plus difficile .. si le GC a déjà collecté l'objet ... Cela se produit généralement si vous essayez de trouver un objet à l'aide de chaînes ... Autrement dit, en le trouvant par le nom de l'objet, il peut arriver que le GC soit déjà nettoyé ... C'est difficile à trouver et deviendra un problème ... Une meilleure façon de résoudre ce problème est de faire des vérifications nulles partout où cela est nécessaire pendant le processus de développement. Cela vous fera gagner beaucoup de temps.
En recherchant par nom, je veux dire qu'un cadre vous permet de FIndObjects en utilisant des chaînes et le code pourrait ressembler à ceci: FindObject ("ObjectName");
la source
Littéralement, la façon la plus simple de corriger une NullReferenceExeption a deux façons. Si vous avez un GameObject par exemple avec un script attaché et une variable nommée rb (rigidbody), cette variable commencera nulle lorsque vous démarrez votre jeu.
C'est pourquoi vous obtenez une NullReferenceExeption car l'ordinateur n'a pas de données stockées dans cette variable.
Je vais utiliser une variable RigidBody comme exemple.
Nous pouvons ajouter des données très facilement de plusieurs manières:
Ensuite, allez dans votre script et tapez
rb = GetComponent<Rigidbody>();
Cette ligne de code fonctionne mieux sous vos fonctions
Start()
ouAwake()
.rb = AddComponent<RigidBody>();
Notes supplémentaires: Si vous voulez que l'unité ajoute un composant à votre objet et que vous ayez oublié d'en ajouter un, vous pouvez taper
[RequireComponent(typeof(RigidBody))]
au-dessus de votre déclaration de classe (l'espace en dessous de tous vos usages).Profitez et amusez-vous à créer des jeux!
la source
Si nous considérons des scénarios courants où cette exception peut être levée, l'accès aux propriétés avec un objet en haut.
Ex:
ici, si l'adresse est nulle, vous obtiendrez NullReferenceException.
Donc, comme pratique, nous devons toujours utiliser la vérification nulle, avant d'accéder aux propriétés de ces objets (spécialement en générique)
la source
Il s'agit essentiellement d'une exception de référence Null . Comme le déclare Microsoft-
Qu'est-ce que ça veut dire?
Cela signifie que si un membre qui n'a aucune valeur et que nous faisons en sorte que ce membre effectue certaines tâches, le système lancera sans aucun doute un message et dira -
"Hé, attendez, ce membre n'a aucune valeur, il ne peut donc pas exécuter la tâche que vous lui remettez."
L'exception elle-même dit que quelque chose est référé mais dont la valeur n'est pas définie. Cela signifie donc que cela se produit uniquement lors de l'utilisation de types de référence, car les types de valeur ne sont pas nullables.
NullReferenceException ne se produira pas si nous utilisons des membres de type Value.
Le code ci-dessus montre une chaîne simple qui est affectée d'un null valeur .
Maintenant, lorsque j'essaie d'imprimer la longueur de la chaîne str , j'obtiens une exception non gérée de type «System.NullReferenceException» , car le membre str pointe vers null et il ne peut pas y avoir de longueur nulle.
' NullReferenceException ' se produit également lorsque nous oublions d'instancier un type de référence.
Supposons que j'ai une classe et une méthode membre. Je n'ai pas instancié ma classe, mais seulement nommé ma classe. Maintenant, si j'essaie d'utiliser la méthode, le compilateur générera une erreur ou émettra un avertissement (selon le compilateur).
Le compilateur pour le code ci-dessus génère une erreur indiquant que la variable obj n'est pas affectée, ce qui signifie que notre variable a des valeurs nulles ou rien. Le compilateur pour le code ci-dessus génère une erreur indiquant que la variable obj n'est pas affectée, ce qui signifie que notre variable a des valeurs nulles ou rien.
Pourquoi cela se produit-il?
NullReferenceException survient en raison de notre faute pour ne pas avoir vérifié la valeur de l'objet. Nous laissons souvent les valeurs des objets non contrôlées dans le développement du code.
Elle survient également lorsque nous oublions d'instancier nos objets. L'utilisation de méthodes, de propriétés, de collections, etc. qui peuvent renvoyer ou définir des valeurs nulles peut également être la cause de cette exception.
comment ca peut etre evite?
Il existe différentes façons et méthodes pour éviter cette exception renommée:
Vérification explicite: nous devons respecter la tradition de vérification des objets, propriétés, méthodes, tableaux et collections s'ils sont nuls. Cela peut être simplement implémenté en utilisant des instructions conditionnelles comme if-else if-else etc.
Gestion des exceptions: l'un des moyens importants de gérer cette exception. En utilisant de simples blocs try-catch-finally, nous pouvons contrôler cette exception et également en conserver un journal. Cela peut être très utile lorsque votre application est en phase de production.
Opérateurs nuls: L'opérateur nul coalescent et les opérateurs conditionnels nuls peuvent également être utilisés de manière pratique lors de la définition des valeurs des objets, des variables, des propriétés et des champs.
Débogueur: Pour les développeurs, nous avons la grande arme du débogage avec nous. Si nous rencontrons NullReferenceException pendant la phase de développement, nous pouvons utiliser le débogueur pour accéder à la source de l'exception.
Méthode intégrée: les méthodes système telles que GetValueOrDefault (), IsNullOrWhiteSpace () et IsNullorEmpty () vérifient les valeurs nulles et affectent la valeur par défaut s'il existe une valeur nulle.
Il y a déjà beaucoup de bonnes réponses ici. Vous pouvez également consulter une description plus détaillée avec des exemples sur mon blog .
J'espère que cela aide aussi!
la source
Si l'on reçoit ce message lors de l'enregistrement ou de la compilation de la génération, fermez simplement tous les fichiers, puis ouvrez n'importe quel fichier à compiler et à enregistrer.
Pour moi, la raison était que j'avais renommé le fichier et que l'ancien fichier était toujours ouvert.
la source