Resharper Gallery页面
变化的历史
该扩展的基本思想是改变Resmanter的静态可取消性分析的行为,以便在不指定显式[NotNull]或[CanBeNull]属性的情况下获得默认的无效注释。例如,方法参数中的参考类型默认情况下是[NotNull] (→他们需要一个显式[CanBeNull]才能变得无效)。

对于针对特定,可配置的,语法元素的启用隐式删除性,适用以下规则。
[NotNull] 。[CanBeNull]属性覆盖它们的无效性。null值的可选方法参数隐含[CanBeNull] 。简而言之,上图中显示的代码...
public string Bar ( string a , [ CanBeNull ] string b , string c = null )
{
// ...
}...隐式变成...
[ NotNull ]
public string Bar ( [ NotNull ] string a , [ CanBeNull ] string b , [ CanBeNull ] string c = null )
{
// ...
}[NotNull]默认情况下没有此扩展,默认的可取消性值是“未知”,这意味着重音器将这些元素排除在其无效分析中。由于此扩展程序的默认可取[CanBeNull]的变化结果,我们必须仅针对特定代码元素(例如参考类型参数作为参数作为参数将其传递为null ),并且不需要大多数情况的明确注释(在大多数情况下(在代码库中)(试图将传递null引用的代码库中的null引用降低至最小值))。
Resharper 9.2引入了对async ( Task<T>返回)方法的无效分析的支持。对于方法返回值的启用隐式删除性, Task<T>返回键入的方法也被隐式[ItemNotNull] (resharper使用此属性来参考任务Task<T> )。对于无效的Task<T>返回值,可以用[ItemCanBeNull]覆盖这一点。
以下示例程序在command.Equals("Hello")中包含一个潜在的NullReferenceException ,因为程序员错过了GetCommand()也可以返回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 ] ;
}使用启用的隐式无效性,该错误将通过Resharper的静态分析检测到。
GetCommand()中的null ,因为此方法将被隐式注释为[NotNull] 。[CanBeNull]添加到GetCommand()来解决此警告。[CanBeNull]属性,Resharper现在会警告Main()中的command.Equals("Hello")呼叫中的潜在NullReferenceException 。在上面的示例中,隐式删除性迫使程序员在GetCommand()上修复缺失的[CanBeNull]属性。这表明了代码库中的[CanBeNull]注释的数量将如何增加,因此不仅可以改善ReSharper的静态分析,还可以改善方法签名的文档(合同)。
该扩展程序的另一个目标是将Resharper的静态分析与Fody Nullguard的隐式无效检查同步。例如,此Fody Weaver注入throw new ArgumentNullException(/*...*/)语句使用与隐式nullability相同的规则进行方法。换句话说,这个编织者增加了运行时检查,以确保RESARARAPER的静态分析。
C#8将获得无效的参考类型,将选项类型带入C#语言。这与隐式无效性的语义相匹配,并且更进一步,因为它将其扩展到当地人,通用参数,因为无效注释在类型级别上起作用。
[ CanBeNull ]
string Bar ( [ CanBeNull ] string a , string b )
{
string result = a ;
return result ;
}...然后对应于...
string ? Bar ( string ? a , string b )
{
string ? result = a ;
return result ;
}这将使将来不必要地进行隐式无效性,同时是一个完美的“升级路径”,因为良好的[CanBeNull]被批准的代码库很容易移植到C#8。
自2016.1版本以来,RESHARPER支持(在“内部模式”中)具有以下差异的可比功能(请参阅代码检查|设置)。
隐式无效...
[NotNull]元素。 显式或隐式[NotNull]元素类型用虚线的下划线突出显示。 (请参阅上面示例屏幕截图中的Bar -method中的粉红色下划线。)这有助于识别所有[NotNull]元素,尤其是从基类和代码元素中推断的[NotNull]元素,这些元素和代码元素被隐含地配置为[NotNull] 。
可以在“隐式无效”选项页面上启用/禁用突出显示,并且可以在Visual Studio的“字体和颜色”选项中配置颜色。
对于代码检查中的特定语法元素,可以启用或禁用隐式无效性|隐式无效选项页面。

也可以使用AssemblyMetadataAttribute通过代码配置隐式删除性。这具有一个优点,即将配置编译到程序集中,以便带有安装的隐式无用性的组件消费者获得与库解决方案中编译的代码元素相同的隐式无效注释。
例子:
[ assembly : AssemblyMetadata ( "ImplicitNullability.AppliesTo" ,
"InputParameters, RefParameters, OutParametersAndResult, Fields, Properties" ) ]
[ assembly : AssemblyMetadata ( "ImplicitNullability.Fields" , "RestrictToReadonly" ) ]
[ assembly : AssemblyMetadata ( "ImplicitNullability.Properties" , "RestrictToGetterOnly" ) ]
[ assembly : AssemblyMetadata ( "ImplicitNullability.GeneratedCode" , "Exclude" ) ]除了无效分析的行为变化外,此扩展程序还提供了以下代码检查警告。
有关这些警告(及其动机)的更多信息,请参见其描述在“ Resmanper Code”检查中|检查严重性选项页面。
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 )
{
} 非常感谢Fabian Schmied支持隐式无效性的设计和概念。