Página de la Galería Resharper
Historia de los cambios
La idea básica de esta extensión es cambiar el comportamiento del análisis de anulabilidad estática de Resharper para que los elementos de código específicos obtengan una anotación de anulabilidad predeterminada sin especificar un atributo explícito [NotNull] o [CanBeNull] . Por ejemplo, los tipos de referencia en los parámetros del método son de forma predeterminada [NotNull] (→ necesitan un explícito [CanBeNull] para volverse anulable).

Con una anulación implícita habilitada para elementos específicos, configurables y de sintaxis, se aplican las siguientes reglas.
[NotNull] .[CanBeNull] .null son implícitamente [CanBeNull] .En pocas palabras, el código se mostró en la imagen de arriba ...
public string Bar ( string a , [ CanBeNull ] string b , string c = null )
{
// ...
}... implícitamente se convierte en ...
[ NotNull ]
public string Bar ( [ NotNull ] string a , [ CanBeNull ] string b , [ CanBeNull ] string c = null )
{
// ...
}[NotNull] Como predeterminado Sin esta extensión, el valor de anulabilidad predeterminado es "desconocido", lo que significa que Resharper excluye estos elementos para su análisis de anulabilidad. Como resultado de la nulabilidad predeterminada modificada de esta extensión, tenemos que colocar anotaciones [CanBeNull] solo para elementos de código específicos (por ejemplo, un parámetro de tipo de referencia donde se debe permitir que pase null como argumento) y no necesitan anotaciones explícitas para la mayoría de los casos (en bases de código que intentan reducir las referencias null de aprobación a un mínimo).
Resharper 9.2 introdujo el soporte para el análisis de anulabilidad para los métodos async ( Task<T> return tiped). Con la anulación implícita habilitada para los valores de retorno del método, los métodos tipificados de retorno Task<T> también se vuelven implícitamente [ItemNotNull] (Resharper usa este atributo para referirse al valor de Task<T> ). Para valores de retorno Task<T> anulable, esto se puede anular con [ItemCanBeNull] .
El siguiente programa de ejemplo contiene una potencial NullReferenceException en command.Equals("Hello") porque el programador se perdió ese GetCommand() también podría devolver 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 ] ;
}Con la anulabilidad implícita habilitada, este error se habría detectado mediante el análisis estático de Resharper.
null en GetCommand() porque este método se anotará implícitamente como [NotNull] .[CanBeNull] a GetCommand() .[CanBeNull] , Resharper ahora advertiría sobre la posible NullReferenceException en el command.Equals("Hello") Llama en Main() . En el ejemplo anterior, la anulabilidad implícita obliga al programador a corregir el atributo que falta [CanBeNull] en GetCommand() . Esto muestra cómo se incrementarán el número de anotaciones [CanBeNull] en la base de código y, por lo tanto, no solo mejorará el análisis estático de Resharper, sino también la documentación de firmas de métodos (contratos).
Otro objetivo de esta extensión es poner en sincronización el análisis estático de Resharper con los controles nulos implícitos de Fody Nullguard. Por ejemplo, este tejedor Fody inyecta throw new ArgumentNullException(/*...*/) para parámetros de método en cuerpos de método que usan las mismas reglas que la anulabilidad implícita . En otras palabras, este tejedor agrega verificaciones de tiempo de ejecución para la anulación del análisis estático de Resharper.
C# 8 obtendrá tipos de referencia anulables que trae tipos de opciones al idioma C#. Esto coincide con la semántica de la anulabilidad implícita y va aún más lejos porque la extiende a los locales, parámetros genéricos, ... porque la anotación de anulabilidad funciona en el nivel de tipo.
[ CanBeNull ]
string Bar ( [ CanBeNull ] string a , string b )
{
string result = a ;
return result ;
}... luego corresponde a ...
string ? Bar ( string ? a , string b )
{
string ? result = a ;
return result ;
} Esto hará innecesario la anulación implícita en el futuro y al mismo tiempo una "ruta de actualización" perfecta porque una buena base de código anotada [CanBeNull] será fácilmente portátil a C# 8.
Desde la versión 2016.1, Resharper es compatible (en el "modo interno") una característica comparable (ver Inspección de código | Configuración ) con las siguientes diferencias.
Nullabilidad implícita ...
[NotNull] . Los tipos de elementos explícitos o implícitos [NotNull] se resaltan con un subrayado punteado. (Consulte los subrayos de rosa en el metro Bar en la captura de pantalla de muestra arriba). Esto ayuda a reconocer todos los elementos [NotNull] , especialmente los elementos [NotNull] inferidos de una clase base y elementos de código que se configuran como implícitamente [NotNull] .
El resaltado se puede habilitar/deshabilitar en la página de opciones de anulabilidad implícita , y los colores se pueden configurar en las opciones de "fuentes y colores" de Visual Studio.
La anulación implícita se puede habilitar o deshabilitar para elementos de sintaxis específicos en la inspección del código | Página de opciones de anulación implícita .

La nullabilidad implícita también se puede configurar mediante código utilizando un AssemblyMetadataAttribute . Esto tiene la ventaja de que la configuración se compila en el ensamblaje para que los consumidores del ensamblaje con anulabilidad implícita instalada obtengan las mismas anotaciones de anulabilidad implícita de los elementos del código compilado como dentro de la solución de la biblioteca.
Ejemplo:
[ assembly : AssemblyMetadata ( "ImplicitNullability.AppliesTo" ,
"InputParameters, RefParameters, OutParametersAndResult, Fields, Properties" ) ]
[ assembly : AssemblyMetadata ( "ImplicitNullability.Fields" , "RestrictToReadonly" ) ]
[ assembly : AssemblyMetadata ( "ImplicitNullability.Properties" , "RestrictToGetterOnly" ) ]
[ assembly : AssemblyMetadata ( "ImplicitNullability.GeneratedCode" , "Exclude" ) ]Además del cambio de comportamiento del análisis de anulabilidad, esta extensión proporcionan las siguientes advertencias de inspección del código.
Para obtener más información sobre estas advertencias (y su motivación), consulte su descripción en la inspección del código Resharper | Página de opciones de gravedad de inspección .
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 )
{
} Muchas gracias a Fabian Schmied por apoyar el diseño y la concepción de la anulabilidad implícita .