Question

J'ai remarqué quelque chose de particulier à propos de Visual Studio. Commencez par saisir ceci (C #) quelque part dans une fonction:

class Foo  
{  
    public void Bar()  
    {  
        string s;
        int i = s.Length;
    }
}

Maintenant, tout de suite, les s dans s.Length seront marqués d'une erreur, en indiquant "> Utilisation de la variable locale non affectée 's' " ;. Par contre, essayez ce code:

class Foo  
{  
    private string s;
    public void Bar()  
    {  
        int i = s.Length;
    }
}

Il compilera et soulignera le s dans chaîne privée s avec un avertissement, indiquant que le champ "Foo.s" n'est jamais attribué, et aura toujours sa valeur par défaut null ".

Maintenant, si VS est si intelligent et sait que s sera toujours nul, pourquoi ne trouve-t-il pas erreur de prendre sa longueur dans le deuxième exemple? Mon hypothèse de départ était la suivante: "Cela ne donne une erreur de compilation que si le compilateur ne peut tout simplement pas terminer son travail. Comme le code fonctionne techniquement tant que vous n'appelez jamais Bar (), il ne s'agit que d'un avertissement. " Sauf que cette explication est invalidée par le premier exemple. Vous pouvez toujours exécuter le code sans erreur tant que vous n'appelez jamais Bar (). Alors qu'est-ce qui donne? Juste un oubli, ou est-ce que je manque quelque chose?

Était-ce utile?

La solution

Le premier exemple (l'erreur) est un exemple de definite-assign et s’applique uniquement aux variables locales. En raison du contexte limité, le compilateur a une prise en main étanche à cette situation. Notez que s n'est pas null, il n'est pas défini.

Dans le deuxième exemple, s est un champ (et sa valeur par défaut est null). Il n'y a pas d'erreur de compilation, mais elle sera toujours interceptée au moment de l'exécution. Ce cas particulier pourrait être piégé mais ce type d'erreur n'est généralement pas détectable par le compilateur.
Par exemple, vous pouvez ajouter une méthode Bar2 () qui attribue une chaîne à s mais l'appelez plus tard que Bar () , ou pas à tout. Cela éliminerait l’avertissement, mais pas l’erreur d’exécution.

Donc, c'est par conception.

Autres conseils

Pour le deuxième exemple, le code est valide, mais il risque de ne pas s'exécuter correctement. Voici plusieurs cas dans lesquels ce programme pourrait exécuter "avec succès"

  • Le compilateur n'est pas correct à 100%. Il est possible de " s " d'avoir une valeur non nulle si une instance est modifiée par réflexion.
  • Le programme peut s'exécuter sans erreur si la méthode Bar n'est jamais appelée
  • Ce programme pourrait être un programme de test qui déclenche une exception NullReferenceException pour des raisons de test

La seule hypothèse que je puisse faire est que dans le deuxième exemple, s pourrait être modifié par réflexion (en utilisant BindingFlags.Private pour accéder au membre privé).

Dans le premier exemple, s est une variable locale et le compilateur peut vérifier si la variable s n'a pas été affectée avant son utilisation.

Dans la seconde, s est une variable globale et il est possible qu’elle ait été initialisée ailleurs dans une classe.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top