Question Qu'est-ce qu'une exception NullReferenceException, et comment la réparer?


J'ai du code et quand il s'exécute, il jette un NullReferenceException, en disant:

La référence d'objet n'est pas définie à une instance d'un objet.

Qu'est-ce que cela signifie, et que puis-je faire pour corriger cette erreur?


1878


origine


Réponses:


Quelle est la cause?

Bottom Line

Vous essayez d'utiliser quelque chose qui est null (ou Nothing dans VB.NET). Cela signifie que vous l'avez défini sur nullou vous ne l'avez jamais réglé.

Comme toute chose, null se passe autour. Si c'est null  dans méthode "A", il se pourrait que la méthode "B" ait passé null  à méthode "A".

null peut avoir différentes significations:

  1. Variables d'objet qui sont non initialisé et donc point à rien. Dans ce cas, si vous accédez à des propriétés ou des méthodes de tels objets, cela provoque NullReferenceException.
  2. Le développeur est en utilisant null intentionnellement pour indiquer qu'il n'y a pas de valeur significative disponible. Notez que C # a le concept de types de données Nullable pour les variables (comme les tables de base de données peuvent avoir des champs Nullable) - vous pouvez assigner null à eux d'indiquer qu'il n'y a pas de valeur stockée, par exemple int? a = null; où le point d'interrogation indique qu'il est autorisé à stocker null dans variable a. Vous pouvez vérifier cela soit avec if (a.HasValue) {...} ou avec if (a==null) {...}. Variables nulles, comme a cet exemple, permet d'accéder à la valeur via a.Value explicitement, ou tout aussi normal via a.
    Remarque que l'accès via a.Value jette un InvalidOperationException au lieu d'un NullReferenceException si a est null - vous devriez faire la vérification au préalable, c'est-à-dire si vous avez une autre variable sur-nullable int b; alors vous devriez faire des missions comme if (a.HasValue) { b = a.Value; } ou plus court if (a != null) { b = a; }.

Le reste de cet article va plus en détail et montre les erreurs que beaucoup de programmeurs font souvent, ce qui peut conduire à un NullReferenceException.

Plus précisement

L'exécution jetant un NullReferenceException  toujours signifie la même chose: vous essayez d'utiliser une référence, et la référence n'est pas initialisée une fois que initialisé, mais est plus maintenant initialisé).

Cela signifie que la référence est null, et vous ne pouvez pas accéder aux membres (tels que les méthodes) à travers un null référence. Le cas le plus simple:

string foo = null;
foo.ToUpper();

Cela va jeter un NullReferenceException à la deuxième ligne, car vous ne pouvez pas appeler la méthode d'instance ToUpper() sur un string ré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 lancée exactement à l'endroit où elle se produit, les règles générales du débogage dans Visual Studio s'appliquent: placer des points d'arrêt stratégiques et inspecter vos variables, soit en plaçant la souris sur leurs noms, en ouvrant une fenêtre (Quick) Watch ou en utilisant les différents panneaux de mise au point comme Locals et Autos.

Si vous voulez savoir où la référence est ou n'est pas définie, faites un clic droit sur son nom et sélectionnez "Trouver 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 joint. Chaque fois que le débogueur interrompt un tel point d'arrêt, vous devez déterminer si vous pensez que la référence est non nulle, inspecter la variable et vérifier qu'elle pointe vers une instance lorsque vous le souhaitez.

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, alors vous aurez un NullReferenceException. Si vous voulez résoudre le problème, trouvez celui qui est nul en réécrivant l'expression à son équivalent plus simple:

var r1 = ref1;
var r2 = r1.ref2;
var r3 = r2.ref3;
r3.member

Plus précisément, dans HttpContext.Current.User.Identity.Name, la HttpContext.Current pourrait être nul, ou le User la propriété pourrait être nulle, ou la Identity la propriété pourrait être nulle.

Indirect

public class Person {
    public int Age { get; set; }
}
public class Book {
    public Person Author { get; set; }
}
public class Example {
    public void Foo() {
        Book b1 = new Book();
        int authorAge = b1.Author.Age; // You never initialized the Author property.
                                       // there is no Person to get an Age from.
    }
}

Si vous voulez éviter la référence null enfant (Person), vous pouvez l'initialiser dans le constructeur de l'objet parent (Book).

Initialiseurs d'objets imbriqués

La même chose s'applique aux initialiseurs d'objets imbriqués:

Book b1 = new Book { Author = { Age = 45 } };

Cela se traduit par

Book b1 = new Book();
b1.Author.Age = 45;

Tandis que le new mot-clé est utilisé, il crée seulement une nouvelle instance de Book, mais pas une nouvelle instance de Person, alors le Author la propriété est toujours null.

Initialiseurs de collection imbriqués

public class Person {
    public ICollection<Book> Books { get; set; }
}
public class Book {
    public string Title { get; set; }
}

Les initialiseurs de collection imbriqués se comportent de la même manière:

Person p1 = new Person {
    Books = {
        new Book { Title = "Title1" },
        new Book { Title = "Title2" },
    }
};

Cela se traduit par

Person p1 = new Person();
p1.Books.Add(new Book { Title = "Title1" });
p1.Books.Add(new Book { Title = "Title2" });

le new Person crée uniquement une instance de Person, mais le Books la collection est encore null. La syntaxe d'initialisation de collection ne crée pas de collection pour p1.Books, cela ne fait que traduire p1.Books.Add(...) déclarations.

Array

int[] numbers = null;
int n = numbers[0]; // numbers is null. There is no array to index.

Éléments de tableau

Person[] people = new Person[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.

Jagged Arrays

long[][] array = new long[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)

public class Person {
    public string Name { get; set; }
}
var people = new List<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

public class Demo
{
    public event EventHandler StateChanged;

    protected virtual void OnStateChanged(EventArgs e)
    {        
        StateChanged(this, e); // Exception is thrown here 
                               // if no event handlers have been attached
                               // to StateChanged event
    }
}

Mauvaises conventions de dénomination:

Si vous avez nommé les champs différemment des locaux, vous avez peut-être réalisé que vous n'avez jamais initialisé le champ.

public class Form1 {
    private Customer customer;

    private void Form1_Load(object sender, EventArgs e) {
        Customer customer = new Customer();
        customer.Name = "John";
    }

    private void Button_Click(object sender, EventArgs e) {
        MessageBox.Show(customer.Name);
    }
}

Cela peut être résolu en suivant la convention pour préfixer les champs avec un trait de soulignement:

private Customer _customer;

Cycle de vie de la page ASP.NET:

public partial class Issues_Edit : System.Web.UI.Page
{
    protected TestIssue myIssue;

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            // Only called on first load, not when button clicked
            myIssue = new TestIssue(); 
        }
    }

    protected void SaveButton_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 NullReferenceException
string firstName = Session["FirstName"].ToString();

Modèles à vue vide ASP.NET MVC

Si l'exception se produit lors du référencement d'une propriété de @Model dans une vue ASP.NET MVC, vous devez comprendre que le Model se met en place dans votre méthode d'action, lorsque vous return 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:

// Controller
public class Restaurant:Controller
{
    public ActionResult Search()
    {
         return View();  // Forgot the provide a Model here.
    }
}

// Razor view 
@foreach (var restaurantSearch in Model.RestaurantSearch)  // Throws.
{
}

<p>@Model.somePropertyName</p> <!-- Also throws -->

Commande de création de contrôle WPF et événements

Les contrôles WPF sont créés lors de l'appel à InitializeComponent dans l'ordre où ils apparaissent dans l'arbre visuel. UNE NullReferenceException sera déclenché dans le cas de contrôles créés au début avec des gestionnaires d'événements, etc. InitializeComponent quelle référence les contrôles créés tardivement.

Par exemple :

<Grid>
    <!-- Combobox declared first -->
    <ComboBox Name="comboBox1" 
              Margin="10"
              SelectedIndex="0" 
              SelectionChanged="comboBox1_SelectionChanged">
        <ComboBoxItem Content="Item 1" />
        <ComboBoxItem Content="Item 2" />
        <ComboBoxItem Content="Item 3" />
    </ComboBox>

    <!-- Label declared later -->
    <Label Name="label1" 
           Content="Label"
           Margin="10" />
</Grid>

Ici comboBox1 est créé avant label1. Si comboBox1_SelectionChanged tente de référencer `label1, il n'aura pas encore été créé.

private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    label1.Content = comboBox1.SelectedIndex.ToString(); // NullReference here!!
}

Modification de l'ordre des déclarations dans le fichier XAML (c'est-à-dire, liste label1 avant comboBox1, ignorant les problèmes de la philosophie de conception, serait au moins résoudre le NullReferenceException ici.

Cast avec as

var myThing = someObject as Thing;

Cela ne lance pas InvalidCastException mais retourne un null quand la distribution échoue (et quand someObject est lui-même nul). Alors soyez conscient de cela.

LINQ FirstOrDefault () et SingleOrDefault ()

Les versions simples First() et Single() jeter des exceptions quand il n'y a rien. Les versions "OrDefault" renvoient null dans ce cas. Alors soyez conscient de cela.

pour chaque

foreach se déclenche lorsque vous essayez d'itérer une collection nulle. Habituellement causé par inattendu null résulte de méthodes qui retournent des collections.

 List<int> list = null;    
 foreach(var v in list) { } // exception

Exemple plus réaliste - sélectionnez les noeuds du document XML. Va lancer si les nœuds ne sont pas trouvés mais le débogage initial montre que toutes les propriétés sont valides:

 foreach (var node in myData.MyXml.DocumentNode.SelectNodes("//Data"))

Façons d'éviter

Vérifier explicitement pour null et ignore les valeurs nulles.

Si vous pensez que la référence est parfois nulle, vous pouvez vérifier qu'elle est null avant d'accéder aux membres de l'instance:

void PrintName(Person p) {
    if (p != null) {
        Console.WriteLine(p.Name);
    }
}

Vérifier explicitement pour null et fournir une valeur par défaut.

Les méthodes appelez vous attendez à retourner une instance peuvent retourner null, par exemple lorsque l'objet recherché ne peut pas être trouvé. Vous pouvez choisir de renvoyer une valeur par défaut lorsque c'est le cas:

string GetCategory(Book b) {
    if (b == null)
        return "Unknown";
    return b.Category;
}

Vérifier explicitement pour null à partir des appels de méthode et lancer une exception personnalisée.

Vous pouvez également lancer une exception personnalisée, uniquement pour l'attraper dans le code appelant:

string GetCategory(string bookTitle) {
    var book = library.FindBook(bookTitle);  // This may return null
    if (book == null)
        throw new BookNotFoundException(bookTitle);  // Your custom exception
    return book.Category;
}

Utilisation Debug.Assert si une valeur ne devrait jamais être null, pour attraper le problème plus tôt que l'exception se produit.

Quand vous savez pendant le développement qu'une méthode peut le faire, mais ne devrait jamais revenir null, vous pouvez utiliser Debug.Assert() se casser le plus tôt possible quand cela arrive:

string GetTitle(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 code

    return book.Title; // Will never throw NullReferenceException in Debug mode.
}

Bien que cette vérification ne finira pas dans votre version de construction, le faisant jeter le NullReferenceException encore quand book == null à l'exécution en mode de publication.

Utilisation GetValueOrDefault() pour les types valeur nullable pour fournir une valeur par défaut quand ils sont null.

DateTime? appointment = null;
Console.WriteLine(appointment.GetValueOrDefault(DateTime.Now));
// Will display the default value provided (DateTime.Now), because appointment is null.

appointment = new DateTime(2022, 10, 20);
Console.WriteLine(appointment.GetValueOrDefault(DateTime.Now));
// Will display the appointment date, not the default

Utilisez l'opérateur de coalescence nulle: ?? [C #] ou If() [VB].

Le raccourci pour fournir une valeur par défaut quand un null est rencontré:

IService CreateService(ILogger log, Int32? frobPowerLevel)
{
    var serviceImpl = new MyService(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 null: ?. ou ?[x] pour les tableaux (disponibles en C # 6 et VB.NET 14):

Ceci est également parfois appelé la navigation de sécurité ou Elvis (après sa forme) opérateur. Si l'expression sur le côté gauche de l'opérateur est null, alors le côté droit ne sera pas évalué, et null est retourné à la place. Cela signifie des cas comme celui-ci:

var title = person.Title.ToUpper();

Si la personne n'a pas de titre, cela va créer une exception parce qu'elle essaie d'appeler ToUpper sur une propriété avec une valeur nulle.

En C # 5 et ci-dessous, ceci peut être gardé avec:

var title = person.Title == null ? null : person.Title.ToUpper();

Maintenant, la variable title sera null au lieu de lancer une exception. C # 6 introduit une syntaxe plus courte pour ceci:

var title = person.Title?.ToUpper();

Cela entraînera la variable de titre étant null, et l'appel à ToUpper n'est pas fait si person.Title est null.

Bien sûr toi encore avoir à vérifier title pour null ou utiliser l'opérateur de condition null avec l'opérateur de fusion null (??) pour fournir une valeur par défaut:

// regular null check
int titleLength = 0;
if (title != null)
    titleLength = title.Length; // If title is null, this would throw NullReferenceException

// combining the `?` and the `??` operator
int titleLength = title?.Length ?? 0;

De même, pour les tableaux, vous pouvez utiliser ?[i] comme suit:

int[] myIntArray=null;
var i=5;
int? elem = myIntArray?[i];
if (!elem.HasValue) Console.WriteLine("No value");

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 le ith élément.

Techniques spéciales pour le débogage et la correction de derefs nuls dans les itérateurs

C # supporte les "blocs d'itérateurs" (appelés "générateurs" dans d'autres langages populaires). Les exceptions de déréférencement nul peuvent être particulièrement difficiles à déboguer dans les blocs d'itérateur en raison d'une exécution différée:

public IEnumerable<Frob> GetFrobs(FrobFactory f, int count)
{
    for (int i = 0; i < count; ++i)
      yield return f.MakeFrob();
}
...
FrobFactory factory = whatever;
IEnumerable<Frobs> frobs = GetFrobs();
...
foreach(Frob frob in frobs) { ... }

Si whatever résulte en null puis MakeFrob va jeter. Maintenant, vous pourriez penser que la bonne chose à faire est la suivante:

// DON'T DO THIS
public IEnumerable<Frob> GetFrobs(FrobFactory f, int count)
{
    if (f == null) 
      throw new ArgumentNullException("f", "factory must not be null");
    for (int i = 0; i < count; ++i)
      yield return f.MakeFrob();
}

Pourquoi est-ce faux? Parce que le bloc d'itération ne fait pas courir jusqu'à ce que le foreach! L'appel à GetFrobs renvoie simplement un objet qui quand itéré exécutera le bloc de l'itérateur.

En écrivant une vérification nulle comme ceci vous empêchez le déréférencement nul, mais vous déplacez l'exception d'argument nul au point de la itération, pas au point de appel, et c'est très confus pour déboguer.

Le correctif correct est:

// DO THIS
public IEnumerable<Frob> GetFrobs(FrobFactory f, int count)
{
    // No yields in a public method that throws!
    if (f == null) 
      throw new ArgumentNullException("f", "factory must not be null");
    return GetFrobsForReal(f, count);
}
private IEnumerable<Frob> GetFrobsForReal(FrobFactory f, int count)
{
    // Yields in a private method
    Debug.Assert(f != null);
    for (int i = 0; i < count; ++i)
      yield return f.MakeFrob();
}

C'est-à-dire, faites une méthode d'assistance privée qui a la logique de bloc d'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 arrive immédiatement, puis GetFrobsForReal s'exécute lorsque la séquence est itérée.

Si vous examinez la source de référence de LINQ to Objects, vous verrez que cette technique est utilisée partout. Il est légèrement plus maladroit à écrire, mais cela facilite beaucoup le débogage des erreurs de nullité. Optimisez votre code pour la commodité de l'appelant, pas la commodité de l'auteur.

Une remarque sur les déréférences nulles dans un code non sécurisé

C # a un mode «dangereux» qui, comme son nom l'indique, est 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 devriez 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érencement d'une null aiguille produit la même exception que déréférencer une null référence
  • déréférencement d'un pointeur non nul invalide pouvez produire cette exception dans certaines circonstances

Pour comprendre pourquoi cela est, il aide à comprendre comment .NET produit des exceptions de déréférencement nul en premier lieu. (Ces détails s'appliquent à .NET s'exécutant sous 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 mémoire virtuel de nombreuses "pages" de mémoire qui sont suivies par le système d'exploitation. Chaque page de la mémoire comporte des drapeaux qui déterminent comment elle peut être utilisée: lecture, écriture, exécution, etc. le le plus bas la page est marquée comme "produire une erreur si jamais elle est utilisée".

Un pointeur NULL et une référence NULL en C # sont tous les deux représentés en interne sous la forme d'un nombre zéro. Ainsi, toute tentative de déréférencement dans le stockage de mémoire correspondant provoque une erreur du système d'exploitation. L'exécution .NET détecte ensuite cette erreur et la transforme en exception de déréférencement nul.

C'est pourquoi déréférencer à la fois un pointeur nul et une référence null produit la même exception.

Qu'en est-il du deuxième point? Déréférencement 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 par conséquent la même exception.

Pourquoi cela a-t-il un sens? Eh bien, supposons que nous ayons une structure contenant deux ints, et un pointeur non géré égal à null. Si nous tentons de déréférencer le second int 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 un déréférencement nul parce que nous arrivons à cette adresse via le null.

Si vous travaillez avec un code non sécurisé et que vous obtenez une exception de déréférencement nul, sachez que le pointeur incriminé n'a pas besoin d'être nul. Cela peut être n'importe quel endroit dans la page la plus basse, et cette exception sera produite.


2107



NullReference Exception - Visual Basic

le NullReference Exception pour Visual Basic n'est pas différent de celui C #. Après tout, ils rapportent tous les deux la même exception définie dans le .NET Framework qu'ils utilisent tous les deux. Les causes uniques à 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 Stack Overflow. Ceci est pour maximiser la pertinence en utilisant le sortes des situations souvent vues dans les messages. Un peu plus d'explication est également fournie pour ceux qui pourraient en avoir besoin. Un exemple similaire à la vôtre est très probablement répertorié ici.

Remarque:

  1. 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 une NullReferenceException (NRE), comment le trouver, comment le réparer et comment l'éviter. Un NRE peut être causé de plusieurs façons, il est peu probable que ce soit votre seule rencontre.
  2. Les exemples (à partir des messages Stack Overflow) ne montrent pas toujours la meilleure façon de faire quelque chose en premier lieu.
  3. Typiquement, 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 de ceux-ci:

  • Votre code déclaré une variable d'objet, mais il n'a pas initialiser (créer une instance ou 'instancier' il)
  • Quelque chose que votre code supposait initialiser un objet, n'a pas
  • Éventuellement, d'autres codes invalident prématurément un objet encore en usage

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 savoir lequel. Puis déterminez pourquoi il n'est pas initialisé. Maintenez la souris sur les différentes variables et Visual Studio (VS) montrera leurs valeurs - le coupable sera Nothing.

IDE debug display

Vous devez également supprimer tous les blocs Try / Catch du code approprié, en particulier ceux où il n'y a rien dans le bloc Catch. Cela provoquera le blocage de votre code lorsqu'il essayera d'utiliser un objet qui est Nothing. Voici ce que tu veux parce qu'il va identifier exactement emplacement du problème, et vous permettent d'identifier l'objet qui le provoque.

UNE MsgBox dans le Catch qui affiche Error while... sera de peu d'aide. Cette méthode conduit également à très mauvais Stack Overflow, car vous ne pouvez pas décrire l'exception réelle, l'objet impliqué ou même la ligne de code où cela se produit.

Vous pouvez également utiliser le Locals Window (Déboguer -> Windows -> Locals) pour examiner vos objets.

Une fois que vous savez quoi et où le problème est, 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

Dim reg As CashRegister
...
TextBox1.Text = reg.Amount         ' NRE

Le problème est que Dim ne crée pas de CashRegister objet; il déclare seulement une variable nommée reg de ce type. Déclaration une variable d'objet et la création d'un exemple sont deux choses différentes.

Remède

le New L'opérateur peut souvent être utilisé pour créer l'instance lorsque vous le déclarez:

Dim reg As New CashRegister        ' [New] creates instance, invokes the constructor

' Longer, more explicit form:
Dim reg As CashRegister = New CashRegister

Quand il est seulement approprié de créer l'instance plus tard:

Private reg As CashRegister         ' Declare
  ...
reg = New CashRegister()            ' Create instance

Remarque: Ne pas utilisation Dim à nouveau dans une procédure, y compris le constructeur (Sub New):

Private reg As CashRegister
'...

Public Sub New()
   '...
   Dim reg As New CashRegister
End Sub

Cela va créer un local variable, reg, qui n'existe que dans ce contexte (sub). le reg variable avec le niveau du module Scope que vous utiliserez partout ailleurs reste Nothing.

Manquant le New opérateur est la première cause de NullReference Exceptions vu dans les questions Stack Overflow examinés.

Visual Basic essaie de rendre le processus effacer à plusieurs reprises en utilisant New: En utilisant le New L'opérateur crée un Nouveau objet et appels Sub New - le constructeur - où votre objet peut effectuer toute autre initialisation.

Pour être clair, Dim (ou Private) seulement déclare une variable et son Type. le Portée de la variable - qu'elle existe pour l'ensemble du module / de la classe ou est locale à une procédure - est déterminée par  c'est déclaré. Private | Friend | Public définit le niveau d'accès, pas Portée.

Pour plus d'informations, voir:


Tableaux

Les tableaux doivent également être instanciés:

Private arr as String()

Ce tableau a seulement été déclaré, pas créé. Il existe plusieurs façons d'initialiser un tableau:

Private arr as String() = New String(10){}
' or
Private arr() As String = New String(10){}

' For a local array (in a procedure) and using 'Option Infer':
Dim arr = New String(10) {}

Remarque: à partir de VS 2010, lors de l'initialisation d'un tableau local à l'aide d'un fichier littéral et Option Infer, la As <Type> et New les éléments sont facultatifs:

Dim myDbl As Double() = {1.5, 2, 9.9, 18, 3.14}
Dim myDbl = New Double() {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 affectées. Les déclarations de niveau classe / module nécessitent toujours As <Type> avec Option Strict:

Private myDoubles As Double() = {1.5, 2, 9.9, 18, 3.14}

Exemple: tableau d'objets de classe

Dim arrFoo(5) As Foo

For i As Integer = 0 To arrFoo.Count - 1
   arrFoo(i).Bar = i * 10       ' Exception
Next

Le tableau a été créé, mais le Fooles objets qui s'y trouvent n'ont pas.

Remède

For i As Integer = 0 To arrFoo.Count - 1
    arrFoo(i) = New Foo()         ' Create Foo instance
    arrFoo(i).Bar = i * 10
Next

Utilisant un List(Of T) rendra très difficile d'avoir un élément sans objet valide:

Dim FooList As New List(Of Foo)     ' List created, but it is empty
Dim f As Foo                        ' Temporary variable for the loop

For i As Integer = 0 To 5
    f = New Foo()                    ' Foo instance created
    f.Bar =  i * 10
    FooList.Add(f)                   ' Foo object added to list
Next

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.

Private myList As List(Of String)
..
myList.Add("ziggy")           ' NullReference

Vous obtenez la même exception pour la même raison - myList a été seulement déclaré, mais aucune instance créée. Le remède est le même:

myList = New List(Of String)

' Or create an instance when declared:
Private myList As New List(Of String)

Un oubli commun est une classe qui utilise une collection Type:

Public Class Foo
    Private barList As List(Of Bar)

    Friend Function BarCount As Integer
        Return barList.Count
    End Function

    Friend Sub AddItem(newBar As Bar)
        If barList.Contains(newBar) = False Then
            barList.Add(newBar)
        End If
    End Function

L'une ou l'autre procédure entraînera un NRE, car barList est seulement déclaré, non instancié. Créer une instance de Foo ne créera pas également une instance de l'interne barList. Cela a peut-être été l'intention de le faire dans le constructeur:

Public Sub New         ' Constructor
    ' Stuff to do when a new Foo is created...
    barList = New List(Of Bar)
End Sub

Comme précédemment, c'est incorrect:

Public Sub New()
    ' Creates another barList local to this procedure
     Dim barList As New List(Of Bar)
End Sub

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 opportunités pour une référence nulle car il peut y avoir plusieurs objets (Command, Connection, Transaction, Dataset, DataTable, DataRows....) en cours d'utilisation. Remarque: Peu importe le fournisseur de données que vous utilisez: MySQL, SQL Server, OleDB, etc. concepts sont identiques.

Exemple 1

Dim da As OleDbDataAdapter
Dim ds As DataSet
Dim MaxRows As Integer

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 auparavant, le ds L'objet Dataset a été déclaré, mais une instance n'a jamais été créée. le DataAdapter remplira un existant DataSet, n'en crée pas. Dans ce cas, depuis ds est une variable locale, l'IDE vous prévient que cela pourrait arriver:

img

Lorsqu'il est déclaré en tant que variable de niveau module / classe, comme cela semble être le cas avec 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

Dim ds As New DataSet

Exemple 2

ds = New DataSet
da = New OleDBDataAdapter(sql, con)
da.Fill(ds, "Employees")

txtID.Text = ds.Tables("Employee").Rows(0).Item(1)
txtID.Name = ds.Tables("Employee").Rows(0).Item(2)

Une faute de frappe est un problème ici: Employees contre Employee. Il n'y avait pas DataTable nommé "Employee" créé, donc un NullReferenceException résultats essayant d'y accéder. Un autre problème potentiel est de supposer qu'il y aura Items ce qui peut ne pas être le cas lorsque le SQL inclut une clause WHERE.

Remède

Comme cela utilise une table, en utilisant Tables(0) évitera les fautes d'orthographe. Examiner Rows.Count peut aussi aider:

If ds.Tables(0).Rows.Count > 0 Then
    txtID.Text = ds.Tables(0).Rows(0).Item(1)
    txtID.Name = ds.Tables(0).Rows(0).Item(2)
End If

Fill est une fonction renvoyant le nombre de Rows affecté qui peut également être testé:

If da.Fill(ds, "Employees") > 0 Then...

Exemple 3

Dim da As New 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 As New DataSet
da.Fill(ds)

If ds.Tables("TICKET_RESERVATION").Rows.Count > 0 Then

le DataAdapter fournira TableNames 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érence la table par index:

If ds.Tables(0).Rows.Count > 0 Then

Voir également Classe DataTable.


Chemins d'objet / imbriqués

If myFoo.Bar.Items IsNot Nothing Then
   ...

Le code ne fait que tester Items alors que les deux myFoo et Bar peut aussi être Rien. le remède est de tester la chaîne entière ou le chemin des objets un à la fois:

If (myFoo IsNot Nothing) AndAlso
    (myFoo.Bar IsNot Nothing) AndAlso
    (myFoo.Bar.Items IsNot Nothing) Then
    ....

AndAlso est important. Les tests subséquents ne seront pas effectués une fois le premier False la condition est rencontrée. Cela permet au code de «forer» en toute sécurité dans le (s) objet (s) un «niveau» à la fois, en évaluant myFoo.Bar seulement après (et si) myFoo est déterminé pour être valide. Les chaînes d'objets ou les chemins peuvent devenir assez longs lors du codage d'objets complexes:

myBase.myNodes(3).Layer.SubLayer.Foo.Files.Add("somefilename")

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:

myWebBrowser.Document.GetElementById("formfld1").InnerText = "some value"

Ici, myWebBrowser ou Document pourrait être Rien ou le formfld1 l'élément peut ne pas exister.


Contrôles de l'interface utilisateur

Dim cmd5 As New 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.SelectedItem pourrait bien être Nothing, alors ListBox1.SelectedItem.ToString résultera en un NRE.

Remède

Validez les données avant de l'utiliser (utilisez également Option Strict et les paramètres SQL):

Dim expiry As DateTime         ' for text date validation
If (ComboBox5.SelectedItems.Count > 0) AndAlso
    (ListBox1.SelectedItems.Count > 0) AndAlso
    (ComboBox2.SelectedItems.Count > 0) AndAlso
    (DateTime.TryParse(expiry.Text, expiry) Then

    '... do stuff
Else
    MessageBox.Show(...error message...)
End If

Alternativement, vous pouvez utiliser (ComboBox5.SelectedItem IsNot Nothing) AndAlso...


Formulaires Visual Basic

Public Class 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 As New List(Of TextBox) From {TextBox1, TextBox2, TextBox3 ...}

    ' Immediate NRE:
    Private somevar As String = Me.Controls("TextBox1").Text

C'est une façon assez courante d'obtenir un NRE. En C #, selon la façon dont il est codé, l'EDI indiquera que 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 VB seulement. Il est également complexe car il peut entraîner une cascade d'échecs.

Les tableaux et les collections ne peuvent pas être initialisés de cette façon. Ce code d'initialisation s'exécutera avant le constructeur crée le Form ou la Controls. Par conséquent:

  • Les listes et la collection seront simplement vides
  • Le tableau contiendra cinq éléments de Nothing
  • le somevar l'affectation se traduira par un NRE immédiat car Rien n'a pas .Text propriété

Référencer les éléments du tableau plus tard entraînera un NRE. Si vous faites cela dans Form_Load, en raison d'un bug étrange, l'IDE Peut-être pas signaler l'exception quand cela arrive. L'exception apparaîtra plus tard lorsque votre code essaie d'utiliser le tableau. Cette "exception silencieuse" est détaillé dans ce post. 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 Form Load event), les exceptions peuvent ne pas être signalées, le code quitte la procédure et affiche simplement le formulaire.

Comme aucun autre code dans votre Sub New ou Form Load l'événement se déroulera après le NRE, beaucoup d'autres choses peut être laissé non initialisé.

Sub Form_Load(..._
   '...
   Dim name As String = NameBoxes(2).Text        ' NRE
   ' ...
   ' More code (which will likely not be executed)
   ' ...
End Sub

Remarque Ceci s'applique à toutes les références de contrôle et de composants qui les rendent illégales là où elles sont:

Public Class Form1

    Private myFiles() As String = Me.OpenFileDialog1.FileName & ...
    Private dbcon As String = OpenFileDialog1.FileName & ";Jet Oledb..."
    Private studentName As String = TextBox13.Text

Remède partiel

Il est curieux que VB ne fournisse pas d'avertissement, mais le remède est de déclarer les conteneurs au niveau de la forme, mais initialiser les dans le gestionnaire d'événements de formulaire de charge lorsque les contrôles faire exister. Cela peut être fait dans Sub New tant que votre code est après le InitializeComponent appel:

' Module level declaration
Private NameBoxes as TextBox()
Private studentName As String

' 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 de conteneur (comme un GroupBox ou Panel) ne sera pas trouvé 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 ces cas, Nothing seront à nouveau stockés dans ces éléments de tableau et un résultat NRE apparaîtra lorsque vous tenterez de le référencer.

Ceux-ci devraient être faciles à trouver maintenant que vous savez ce que vous cherchez: VS shows you the error of your ways

"Button2" réside sur un Panel

Remède

Plutôt que des références indirectes par nom en utilisant le formulaire Controlscollection, utilisez la référence de contrôle:

' Declaration
Private 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 renvoyant rien

Private bars As New List(Of Bars)        ' Declared and created

Public Function BarList() As List(Of Bars)
    bars.Clear
    If someCondition Then
        For n As Integer = 0 to someValue
            bars.Add(GetBar(n))
        Next n
    Else
        Exit Function
    End If

    Return bars
End Function

C'est un cas où l'EDI vous avertira que 'pas tous les chemins renvoient une valeur et un NullReferenceException peut résulter'. Vous pouvez supprimer l'avertissement en remplaçant Exit Function avec Return Nothing, mais cela ne résout pas le problème. Tout ce qui essaie d'utiliser le retour quand someCondition = False résultera en un NRE:

bList = myFoo.BarList()
For Each b As Bar in bList      ' EXCEPTION
      ...

Remède

Remplacer Exit Function dans la fonction avec Return bList. Retourner un vide  List n'est pas la même chose que le retour Nothing. S'il y a une chance qu'un objet retourné puisse être Nothing, testez avant de l'utiliser:

 bList = myFoo.BarList()
 If bList IsNot Nothing Then...

Mis en œuvre mal essayé / attrapé

Un Try / Catch mal implémenté peut masquer le problème et en entraîner de nouveaux:

Dim dr As SqlDataReader
Try
    Dim lnk As LinkButton = TryCast(sender, LinkButton)
    Dim gr As GridViewRow = DirectCast(lnk.NamingContainer, GridViewRow)
    Dim eid As String = 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()
    End If
    command = New SqlCommand(sqlQry, connection)

    'More code fooing and barring

    dr = command.ExecuteReader()
    If dr.Read() Then
        lblFirstName.Text = Convert.ToString(dr("FirstName"))
        ...
    End If
    mpe.Show()
Catch

Finally
    command.Dispose()
    dr.Close()             ' <-- NRE
    connection.Close()
End Try

Ceci est un cas où un objet n'est pas créé comme prévu, mais démontre également l'utilité d'un compteur vide Catch.

Il y a une virgule supplémentaire dans le SQL (après 'mailaddress') qui entraîne une exception à .ExecuteReader. Après le Catch ne fait rien, Finally essaie d'effectuer un nettoyage, mais puisque vous ne pouvez pas Close une null DataReader objet, un tout nouveau NullReferenceException résultats.

Un vide Catch bloc est le terrain de jeu du diable. Cet OP était déconcerté pourquoi il obtenait un NRE dans le Finally bloc. Dans d'autres situations, un vide Catch 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 fournit la même valeur de divertissement.)

Remède

N'utilisez pas de blocs Try / Catch vides - laissez le code s'écraser afin de pouvoir 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 de la personne uniquement qualifiée pour les corriger - le développeur.


DBNull n'est pas la même chose que Nothing

For Each row As DataGridViewRow In dgvPlanning.Rows
    If Not IsDBNull(row.Cells(0).Value) Then
        ...

le IsDBNull fonction est utilisée pour tester si un valeur équivaut à System.DBNull: De MSDN:

La valeur System.DBNull indique que l'objet représente des données manquantes ou inexistantes. DBNull n'est pas la même chose que Nothing, ce qui indique qu'une variable n'a pas encore été initialisée.

Remède

If row.Cells(0) IsNot Nothing Then ...

Comme précédemment, vous pouvez tester Nothing, puis une valeur spécifique:

If (row.Cells(0) IsNot Nothing) AndAlso (IsDBNull(row.Cells(0).Value) = False) Then

Exemple 2

Dim getFoo = (From f In dbContext.FooBars
               Where f.something = something
               Select f).FirstOrDefault

If Not IsDBNull(getFoo) Then
    If IsDBNull(getFoo.user_id) Then
        txtFirst.Text = getFoo.first_name
    Else
       ...

FirstOrDefault renvoie le premier élément ou la valeur par défaut, qui est Nothing pour les types de référence et jamais DBNull:

If getFoo IsNot Nothing Then...

Contrôles

Dim chk As CheckBox

chk = CType(Me.Controls(chkName), CheckBox)
If chk.Checked Then
    Return chk
End If

Si un CheckBox avec chkName ne peut pas être trouvé (ou existe dans un GroupBox), puis chk ne sera rien et tentera de référencer toute propriété entraînera une exception.

Remède

If (chk IsNot Nothing) AndAlso (chk.Checked) Then ...

Le DataGridView

La DGV a quelques bizarreries vues périodiquement:

dgvBooks.DataSource = loan.Books
dgvBooks.Columns("ISBN").Visible = True       ' NullReferenceException
dgvBooks.Columns("Title").DefaultCellStyle.Format = "C"
dgvBooks.Columns("Author").DefaultCellStyle.Format = "C"
dgvBooks.Columns("Price").DefaultCellStyle.Format = "C"

Si dgvBooks a AutoGenerateColumns = True, il va créer les colonnes, mais il ne les nomme pas, donc le code ci-dessus échoue quand il les référence par leur nom.

Remède

Nommez les colonnes manuellement ou faites référence par index:

dgvBooks.Columns(0).Visible = True

Exemple 2 - Attention au NewRow

xlWorkSheet = xlWorkBook.Sheets("sheet1")

For i = 0 To myDGV.RowCount - 1
    For j = 0 To myDGV.ColumnCount - 1
        For k As Integer = 1 To myDGV.Columns.Count
            xlWorkSheet.Cells(1, k) = myDGV.Columns(k - 1).HeaderText
            xlWorkSheet.Cells(i + 2, j + 1) = myDGV(j, i).Value.ToString()
        Next
    Next
Next

Quand ton DataGridView a AllowUserToAddRows comme True (par défaut), le Cells dans le vide / nouvelle ligne en bas contiendra tous Nothing. La plupart des tentatives d'utilisation du contenu (par exemple, ToString) entraînera un NRE.

Remède

Utiliser un For/Each boucle et tester le IsNewRow propriété pour déterminer si c'est la dernière rangée. Cela fonctionne si AllowUserToAddRows est vrai ou pas:

For Each r As DataGridViewRow in myDGV.Rows
    If r.IsNewRow = False Then
         ' ok to use this row

Si vous utilisez un For n boucle, modifier le nombre de lignes ou utiliser Exit For quand IsNewRow est vrai.


My.Settings (StringCollection)

Dans certaines circonstances, essayer d'utiliser un objet de My.Settings qui est un StringCollection peut entraîner un 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

Puisque VB gère les paramètres pour vous, il est raisonnable de s'attendre à ce qu'il initialise la collection. Ce sera le cas, mais seulement si vous avez déjà ajouté une entrée initiale à la collection (dans l'éditeur de paramètres). Puisque la collection est (apparemment) initialisée lorsqu'un élément est ajouté, il reste Nothing lorsqu'il n'y a aucun élément dans l'éditeur de paramètres à ajouter.

Remède

Initialiser la collection de paramètres dans le formulaire Load gestionnaire d'événements, si / quand nécessaire:

If My.Settings.FooBars Is Nothing Then
    My.Settings.FooBars = New System.Collections.Specialized.StringCollection
End If

Typiquement, le Settings La collecte n'aura besoin d'être initialisée que la première fois que l'application sera exécutée. Un remède alternatif consiste à ajouter une valeur initiale à votre collection dans Projet -> Paramètres | FooBars, enregistrez le projet, puis supprimez la valeur false.


Points clés

Vous avez probablement oublié le New opérateur.

ou

Quelque chose que vous avez supposé fonctionnerait parfaitement pour retourner un objet initialisé à votre code, n'a pas fait.

N'ignorez pas les avertissements du compilateur (jamais) et utilisez Option Strict On (toujours).


MSDN NullReference Exception


273



Un autre scénario est lorsque vous lancez un objet nul dans un type de valeur. Par exemple, le code ci-dessous:

object o = null;
DateTime d = (DateTime)o;

Il va jeter un NullReferenceException sur le casting. Cela semble assez évident dans l'exemple ci-dessus, mais cela peut se produire dans d'autres scénarios complexes où l'objet nul a été renvoyé à partir de quelque code que vous ne possédez pas, et la distribution est par exemple générée par un système automatique.

Un exemple de ceci est ce fragment de liaison ASP.NET simple avec le contrôle Calendar:

<asp:Calendar runat="server" SelectedDate="<%#Bind("Something")%>" />

Ici, SelectedDate est en fait une propriété - de DateTime type - de la Calendar Type de contrôle Web, et la liaison pourrait parfaitement retourner quelque chose de null. Le générateur ASP.NET implicite créera un morceau de code qui sera équivalent au code de cast ci-dessus. Et cela soulèvera un NullReferenceException c'est assez difficile à repérer, car il se trouve dans le code généré ASP.NET qui compile bien ...


217



Cela signifie que la variable en question n'est point désignée. Je pourrais générer ceci comme ça:

SqlConnection connection = null;
connection.Open();

Cela va jeter l'erreur parce que pendant que j'ai déclaré la variable "connection", je ne veux rien dire, quand j'essaye d'appeler le membre"Open", il n'y a aucune référence pour résoudre, et il va jeter l'erreur.

Pour éviter cette erreur:

  1. Toujours initialiser vos objets avant d'essayer de faire quoi que ce soit avec eux.
  2. Si vous n'êtes pas sûr que l'objet est null, 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 source numéro un de bugs, à mon humble avis.


146



Cela signifie que votre code utilisait une variable de référence d'objet définie sur null (c'est-à-dire qu'elle ne faisait pas référence à une instance d'objet réelle).

Pour éviter l'erreur, les objets qui pourraient être null devraient ê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
}

135



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/null pour la variable de référence, cela signifie qu'elle ne contient pas de référence à une instance d'un objet existant sur le tas.

Vous n'avez jamais assigné quelque chose à la variable, jamais créé une instance de la valeur assignée à la variable, ou vous avez mis la variable égale à Nothing/null manuellement, ou vous avez appelé une fonction qui définit la variable Nothing/null pour toi.


90



Voici un exemple de cette exception: 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
} 

L'exécution .NET lancera une exception NullReferenceException lorsque vous tenterez d'effectuer une action sur quelque chose qui n'a pas été instancié, c'est-à-dire le code ci-dessus.

Par rapport à une exception ArgumentNullException qui est généralement levée en tant que mesure défensive si une méthode s'attend à ce que ce qui lui est passé n'est pas nul.

Plus d'informations sont en C # NullReferenceException et Null Parameter.


76