Page de galerie Resharper
Histoire des changements
L'idée de base de cette extension est de modifier le comportement de l'analyse nullabilité statique de Resharper afin que les éléments de code spécifiques obtiennent une annotation nullabilité par défaut sans spécifier un attribut explicite [NotNull] ou [CanBeNull] . Par exemple, les types de référence dans les paramètres de la méthode sont par défaut [NotNull] (→ Ils ont besoin d'un [CanBeNull] explicite pour devenir nullable).

Avec une nullabilité implicite activée pour des éléments de syntaxe spécifiques et configurables, les règles suivantes s'appliquent.
[NotNull] .[CanBeNull] .null sont implicitement [CanBeNull] .En un mot, le code s'est montré dans l'image ci-dessus ...
public string Bar ( string a , [ CanBeNull ] string b , string c = null )
{
// ...
}... devient implicitement ...
[ NotNull ]
public string Bar ( [ NotNull ] string a , [ CanBeNull ] string b , [ CanBeNull ] string c = null )
{
// ...
}[NotNull] par défaut Sans cette extension, la valeur nullabilité par défaut est "inconnue", ce qui signifie que Resharper exclut ces éléments pour son analyse nullabilité. À la suite de la modification de l'infinissable par défaut de cette extension, nous devons placer des annotations [CanBeNull] uniquement pour des éléments de code spécifiques (par exemple, un paramètre de type de référence où il devrait être autorisé à passer null comme argument) et n'a pas besoin d'annotations explicites pour la majorité des cas (dans les bases de code qui essaient de réduire les références null à minimum).
Resharper 9.2 a introduit le support pour l'analyse nullabilité pour les méthodes async ( Task<T> return). Avec une nullabilité implicite activée pour les valeurs de retour de méthode, Task<T> RETOUR Les méthodes typées deviennent également implicitement [ItemNotNull] (Resharper utilise cet attribut pour se référer à la valeur de Task<T> ). Pour les valeurs de retour Task<T> nullables, cela peut être remplacé par [ItemCanBeNull] .
Le programme d'exemple suivant contient un potentiel NullReferenceException dans command.Equals("Hello") car le programmeur a manqué que GetCommand() pourrait également retourner null .
public static void Main ( string [ ] args )
{
string command = GetCommand ( args ) ;
if ( command . Equals ( "Hello" ) )
Console . WriteLine ( "Hello World!" ) ;
}
private static string GetCommand ( string [ ] args )
{
if ( args . Length < 1 )
return null ;
return args [ 0 ] ;
}Avec une nullabilité implicite activée, ce bug aurait été détecté par l'analyse statique de Resharper.
null dans GetCommand() car cette méthode serait implicitement annotée comme [NotNull] .[CanBeNull] pour GetCommand() .[CanBeNull] , Resharper mettrait désormais en garde contre le appel potentiel NullReferenceException dans l' command.Equals("Hello") dans Main() . Dans l'exemple ci-dessus, une nullabilité implicite oblige le programmeur à réparer l'attribut [CanBeNull] manquant sur GetCommand() . Cela montre comment le nombre d'annotations [CanBeNull] sera augmenté dans la base de code et n'améliore donc pas seulement l'analyse statique de Resharper, mais également la documentation des signatures de méthode (contrats).
Un autre objectif de cette extension est de synchroniser l'analyse statique de Resharper avec les contrôles nuls implicites de Fody Nullguard. Par exemple, ce weaver fody injecte throw new ArgumentNullException(/*...*/) pour les paramètres de méthode dans les corps de méthode utilisant les mêmes règles que la nullabilité implicite . En d'autres termes, ce tisserand ajoute des vérifications d'exécution pour une nullabilité à l'analyse statique de Resharper.
C # 8 obtiendra des types de référence nullables qui apportent des types d'options dans la langue C #. Cela correspond à la sémantique de la nullabilité implicite et va encore plus loin car elle l'étend aux locaux, paramètres génériques, ... parce que l'annotation nullabilité fonctionne au niveau du type.
[ CanBeNull ]
string Bar ( [ CanBeNull ] string a , string b )
{
string result = a ;
return result ;
}... puis correspond à ...
string ? Bar ( string ? a , string b )
{
string ? result = a ;
return result ;
} Cela rendra une nullabilité implicite inutile à l'avenir et en même temps, un "chemin de mise à niveau" parfait car une bonne base de code annnée [CanBeNull] sera facilement portable vers C # 8.
Depuis la version 2016.1 Resharper prend en charge (dans le "mode interne") une fonctionnalité comparable (voir Code Inspection | Paramètres ) avec les différences suivantes.
Nullabilité implicite ...
[NotNull] . Les types d'éléments explicites ou implicites [NotNull] sont mis en évidence avec un soulignement en pointillé. (Voir les soulignements roses dans la méthode Bar dans la capture d'écran de l'échantillon ci-dessus.) Cela aide à reconnaître tous les éléments [NotNull] , en particulier les éléments [NotNull] induits d'une classe de base et des éléments de code qui sont configurés comme implicitement [NotNull] .
La mise en évidence peut être activée / désactivée sur la page des options de nullabilité implicite , et les couleurs peuvent être configurées dans les options de "polices et couleurs" de Visual Studio.
La nullabilité implicite peut être activée ou désactivée pour des éléments de syntaxe spécifiques dans l' inspection du code | Page d'options de nullabilité implicite .

La nullabilité implicite peut également être configurée par code à l'aide d'un AssemblyMetadataAttribute . Cela a l'avantage que la configuration est compilée dans l'assemblage afin que les consommateurs de l'assemblage avec une nullabilité implicite installée obtiennent les mêmes annotations nullabilité implicites des éléments de code compilés que dans la solution de la bibliothèque.
Exemple:
[ assembly : AssemblyMetadata ( "ImplicitNullability.AppliesTo" ,
"InputParameters, RefParameters, OutParametersAndResult, Fields, Properties" ) ]
[ assembly : AssemblyMetadata ( "ImplicitNullability.Fields" , "RestrictToReadonly" ) ]
[ assembly : AssemblyMetadata ( "ImplicitNullability.Properties" , "RestrictToGetterOnly" ) ]
[ assembly : AssemblyMetadata ( "ImplicitNullability.GeneratedCode" , "Exclude" ) ]En plus du changement de comportement de l'analyse nullabilité, les avertissements d'inspection de code suivants sont fournis par cette extension.
Pour plus d'informations sur ces avertissements (et leur motivation), consultez leur description dans l' inspection du code Resharper | Page d'options de gravité d'inspection .
ID: ImplicitNotNullConflictInHierarchy
abstract class Base
{
public abstract void Method ( [ CanBeNull ] string a ) ;
}
class Derived : Base
{
// "Implicit NotNull conflicts with nullability in base type":
public override void Method ( string a )
{
}
} ID: ImplicitNotNullElementCannotOverrideCanBeNull
abstract class Base
{
[ CanBeNull ]
public abstract string Method ( ) ;
}
class Derived : Base
{
// "Implicit NotNull element cannot override CanBeNull in base type, nullability should be explicit":
public override string Method ( ) => "" ;
} IDS: ImplicitNotNullOverridesUnknownBaseMemberNullability resp. ImplicitNotNullResultOverridesUnknownBaseMemberNullability
class Derived : External . Class /* (external code with unannotated 'Method' and 'Function') */
{
// "Implicit NotNull overrides unknown nullability of base member, nullability should be explicit":
public override void Method ( string a )
{
}
// "Implicit NotNull result or out parameter overrides unknown nullability of base member,
// nullability should be explicit":
public override string Function ( ) => "" ;
} ID: NotNullOnImplicitCanBeNull
// "Implicit CanBeNull element has an explicit NotNull annotation":
void Foo ( [ NotNull ] int ? a )
{
} Un grand merci à Fabian Schmied pour avoir soutenu la conception et la conception de la nullabilité implicite .