reSharper 갤러리 페이지
변화의 역사
이 확장의 기본 아이디어는 특정 코드 요소가 명시 적 [NotNull] 또는 [CanBeNull] 속성을 지정하지 않고 기본 무효성 주석을 얻을 수 있도록 RESHARPER의 정적 무효 성 분석의 동작을 변경하는 것입니다. 예를 들어, 메소드 매개 변수의 참조 유형은 기본적으로 [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] 기본값으로 이 확장이 없으면 기본 무효성 값은 "알 수 없음"이므로 Resharper는 이러한 요소를 무효성 분석을 위해 제외합니다. 이 확장의 변경된 기본 무효성성의 결과로 우리는 특정 코드 요소에 대해서만 [CanBeNull] 주석을 배치해야하며 (예 : 대부분의 경우에 대한 명시 null 주석이 필요하지 않은 참조 유형 매개 변수) (예 : 통과 된 null 참조를 최소로 줄이려는 코드베이스).
Resharper 9.2는 async ( Task<T> return Typed) 방법에 대한 무효성 분석에 대한 지원을 도입했습니다. 메소드 리턴 값에 대한 암시 적 무효 성을 활성화하면 Task<T> return 유형 메소드도 암시 적으로 [ItemNotNull] 이됩니다 (Resharper는이 속성을 사용하여 Task<T> 의 값을 참조합니다). 무효 Task<T> return 값의 경우 [ItemCanBeNull] 로 재정의 할 수 있습니다.
다음 예제 프로그램에는 프로그래머가 GetCommand() null 놓칠 수 있기 때문에 command.Equals("Hello") 의 잠재적 NullReferenceException 포함되어 있습니다.
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] 하는 것에 대해 경고 할 것입니다.GetCommand() 에 [CanBeNull] 추가하여 프로그래머가 해결합니다.[CanBeNull] 속성의 결과로, Resharper는 이제 Main() 에서 command.Equals("Hello") 호출의 잠재적 NullReferenceException 에 대해 경고 할 것입니다. 위의 예에서 암시 적 무 1 그럴 가능성 은 프로그래머가 GetCommand() 에서 누락 된 [CanBeNull] 속성을 수정해야합니다. 이것은 코드 기반에서 [CanBeNull] 주석의 수가 어떻게 증가 할 것인지를 보여줍니다. 따라서 Resharper의 정적 분석뿐만 아니라 메소드 서명 (계약)의 문서화를 향상시킵니다.
이 확장의 또 다른 목표는 Resharper의 정적 분석을 Fody NullGuard의 암시 적 Null 검사와 동기화하는 것입니다. 예를 들어,이 fody weaver는 메소드 매개 변수에 대한 throw new ArgumentNullException(/*...*/) 문장을 암시 적 무효 성과 동일한 규칙을 사용하여 메소드 본문에 던져 넣습니다. 다시 말해이 직물은 런 타임 체 검사를 추가하여 resharper의 정적 분석에 런타임 검사를 추가합니다.
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으로 쉽게 휴대 할 수 있기 때문에 향후 암시 적 무효 성을 불필요하게 만들 것입니다.
Resharper는 버전 2016.1 이후 다음 차이점과 함께 비슷한 기능 (코드 검사 | 설정 참조)을 지원합니다 ( 코드 검사 | 설정 참조).
암시 적 무효 수준 ...
[NotNull] 요소에 대한 유형 강조 표시를 추가합니다. 명시 적 또는 암시 적 [NotNull] 요소 유형은 점선 밑줄로 강조 표시됩니다. (위의 샘플 스크린 샷에서 Bar 에서 분홍색 밑줄이 밑줄을 참조하십시오.) 이것은 암시 적으로 [NotNull] [NotNull] [NotNull] 요소를 인식하는 데 도움이됩니다.
암시 적 Nullability 옵션 페이지에서 강조 표시를 활성화/비활성화 할 수 있으며 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" ) ]귀중한 분석의 동작 변화 외에도 다음 코드 검사 경고는이 확장에 의해 제공됩니다.
이러한 경고 (및 동기 부여)에 대한 자세한 내용은 Resharper 코드 검사에서 설명을 참조하십시오 | 검사 심각도 옵션 페이지.
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에게 큰 감사의 말 을 전합니다.