NullReferenceException lors de l’initialisation de l’object

Pourquoi existe-t-il une exception NullReferenceException lorsque vous essayez de définir la valeur de X dans le code ci-dessous? Cela fonctionne bien lorsque j’utilise un new mot clé lors de l’initialisation de B , mais pourquoi comstack-t-il correctement sans new et échoue ensuite au moment de l’exécution?

https://dotnetfiddle.net/YNvPog

 public class A { public _B B; public class _B { public int X; } } public class Program { public static void Main() { var a=new A{ B={ X=1 } }; } } 

La syntaxe d’initialisation peut être délicate. Dans votre code, vous essayez de définir la valeur de aBX sans d’abord définir la valeur de B Votre code se traduit par:

 var a = new A(); aBX = 1; 

… qui produirait la même exception que vous obtenez maintenant. En effet, aB est initialisé à null sauf si vous créez explicitement une instance pour elle.

Comme vous l’avez noté, cela fonctionnera:

  var a=new A{ B= new _B { X=1 } }; 

Vous pouvez également vous assurer que le constructeur de A initialise un B

 public class A { public _B B = new A._B(); public class _B { public int X; } } 

pourquoi il comstack bien sans nouveau et puis échoue pendant l’exécution?

Cela demanderait trop de travail au compilateur de creuser dans le code de votre classe A et de se rendre compte que B serait définitivement nul à ce moment-là: comme je l’ai indiqué, vous pouvez modifier l’implémentation du constructeur de A pour vous assurer que pas le cas. C’est l’une des raisons pour lesquelles les exceptions de référence nulles constituent le type d’exception le plus courant.

La meilleure stratégie pour éviter cela consiste à initialiser tous vos champs avec des valeurs non NULL dans le constructeur. Si vous ne savez pas quelle valeur leur donner jusqu’à ce que votre constructeur soit appelé, faites en sorte que votre constructeur prenne ces valeurs en tant que parameters. Si vous vous attendez à ce que l’un de vos champs n’ait pas toujours une valeur, vous pouvez utiliser un type facultatif tel que ma structure Maybe<> pour forcer les programmeurs à gérer ce fait au moment de la compilation.