C #에서 Null 매개 변수 검사
C #에서 null이 유효한 값이 아닌 모든 함수에 다음 변수 null 검사를 추가하는 데 좋은 이유 (더 나은 오류 메시지 제외)가? 분명히 사용하는 코드는 어쨌든 예외를 던질 것입니다. 그리고 다만 검사는 코드를 유지 관리하기 더 느리고 어렵게 만듭니다.
void f(SomeType s)
{
if (s == null)
{
throw new ArgumentNullException("s cannot be null.");
}
// Use s
}
예, 그럴만 한 이유가 있습니다.
- null이 무엇인지 정확히 파악합니다.
NullReferenceException
- 조건이 값이 잘못된 입력에서 코드가 오류를 의미하지 않습니다.
- 메서드가 첫 번째 역 참조하기 전에 도달 할 수있는 다른 부작용을 갖기 전에 예외가 발생 하도록합니다.
- 그것은 당신이 뭔가에 자신의 계약을 전달하는 것을 확신 할 수 있다고 확신합니다.
- 그것은 당신의 방법의 요구 사항을 문서화합니다 ( 물론 코드 계약을 사용하는 것이 더 좋습니다)
이제 귀하의 이의 제기 :
- 더 느립니다 : 이것이 실제로 코드의 병목 현상임을 발견 했습니까 , 아니면 추측하고 있습니까? Nullity 검사는 매우 빠르며 대부분의 경우 병목 현상이 발생하지 않습니다.
- 그것은 코드를 유지하기 어렵게 싸다 . 나는 그 반대라고 생각한다. 그 매개 변수가 null 일 수 있는지 여부와 해당 조건이 적용되는 것이 확실한 경우 코드를 사용하는 것이 더 있다고 생각합니다 .
그리고 당신의 주장 :
분명히 사용하는 코드는 어쨌든 예외를 던질 것입니다.
정말? 중히 여기다 :
void f(SomeType s)
{
// Use s
Console.WriteLine("I've got a message of {0}", s);
}
를 사용하는 s
예외는 발생하지 않습니다. s
null이되는 것이 유효하지 않고 있음을 나타냅니다.
이제 인수 유효성 검사를 어디에 두는 [해석] 다른 문제입니다. 자신의 클래스 내의 코드를 신뢰하기로 모든 이용 가능하므로 신경 쓰지에서. 나머지 어셈블리를 신뢰하기로 수 있으므로 내부 메소드에 신경 쓰지 신뢰합니다. 공용 메서드에 대한 인수의 유효성을 거의 확실하게 확인해야합니다.
참고 :의 고유 한 변수 생성자 오버로드 ArgumentNullException
는 다음과 같은 변수 이름이어야합니다.
if (s == null)
{
throw new ArgumentNullException("s");
}
또는 확장 메소드를 생성하여 다소 간결하게 할 수 있습니다.
s.ThrowIfNull("s");
내 버전의 (일반) 확장 메서드에서는 null이 아닌 경우 원래 값을 반환하여 다음과 같은 내용을 사용할 수 있습니다.
this.name = name.ThrowIfNull("name");
너무 신경 쓰지 않는 오버로드 변수 이름을 사용하지 않는 오버로드를 사용합니다.
나는 Jon의 의견에 동의하지만 여기에 한 가지 추가하겠습니다.
명시 적 null 검사를 추가 할 때에 대한 나의 태도는 다음 전제를 기반으로합니다.
- 단위 테스트가 프로그램의 모든 명령문을 실행하는 방법이 있어야합니다.
throw
은 진술 진술 입니다.- 결과의
if
는 진술 입니다. - 따라서 운동 할 수있는 방법이 있어야한다
throw
의를if (x == null) throw whatever;
명령문을 실행할 해당 수있는 방법 이 없으면 테스트 할 수 없으며 Debug.Assert(x != null);
.
해당 명령문을 듣고 수있는 방법이 있으면 실행하는 단위 테스트를 작성하십시오.
-type의 퍼블릭 퍼블릭 메서드는 이러한 방식으로 인수를 확인하는 것이 특히 중요합니다. 사용자가 어떤 미친 짓을하게 될지 전혀 그렇지 않습니다. 그들에게 "이봐, 멍청 아, 잘못하고있어!" 가능한 한 빨리 예외.
private 형식의 private 메서드는 인수를 제어하는 상황에 가능성이 훨씬 더 높으며 인수가 null이 아님을 강력하게 보장합니다. 그 불변성을 문서화하기 위해 어설 션을 사용하십시오.
적없이 명시 if
검사,하기가 매우 파악 어려울 수 있습니다 무엇을 했다 null
코드를 소유하지 않은 경우.
당신이 얻을 경우 NullReferenceException
소스 코드가 내부의 깊은 곳에서, 당신은 당신이 뭘 잘못했는지 알아내는 것이 많은 문제를 발견했습니다.
여러 검사로 인해 if
코드가 눈에 많이 쌓입니다.
매개 변수 참고받는 ArgumentNullException
생성자는 매개 변수 이름이 아닌 메시지입니다.
귀하의 코드는
if (s == null) throw new ArgumentNullException("s");
이 작업을 더 쉽게하기 위해 코드 조각을 작성했습니다.
<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>Check for null arguments</Title>
<Shortcut>tna</Shortcut>
<Description>Code snippet for throw new ArgumentNullException</Description>
<Author>SLaks</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
<SnippetType>SurroundsWith</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>Parameter</ID>
<ToolTip>Paremeter to check for null</ToolTip>
<Default>value</Default>
</Literal>
</Declarations>
<Code Language="csharp"><![CDATA[if ($Parameter$ == null) throw new ArgumentNullException("$Parameter$");
$end$]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
나는 그것을 1 년 동안 사용하고있다.
_ = s ?? throw new ArgumentNullException(nameof(s));
oneliner이고, 폐기 ( _
)는 불필요한 할당이 없음을 의미합니다.
null 개체를 사용하는 경우에는 더 좋은 방법이 필요한 경우 코드 계약을 살펴볼 수 있습니다 .
가장 큰 이점은 처음부터 방법의 요구 사항을 명확하게 할 수 있다는 것입니다. 이것은 코드를 작업하는 다른 개발자들에게 호출자가 여러분의 메서드에 null 값을 보내는 것이 진정한 오류임을 분명히합니다.
이 검사는 다른 코드가 실행되기 전에 메서드 실행도 중지합니다. 즉, 미완성으로 남겨진 방법에 의해 수정되는 것에 대해 걱정할 필요가 없습니다.
해당 예외가 발생하면 일부 디버깅이 절약됩니다.
ArgumentNullException은 null 인 "s"임을 명시 적으로 나타냅니다.
해당 검사가없고 코드가 작동하도록하면 해당 메서드의 식별되지 않은 일부 줄에서 NullReferenceException이 발생합니다. 릴리스 빌드에서는 줄 번호가 없습니다!
int i = Age ?? 0;
따라서 귀하의 예를 들어 :
if (age == null || age == 0)
또는:
if (age.GetValueOrDefault(0) == 0)
또는:
if ((age ?? 0) == 0)
또는 삼항 :
int i = age.HasValue ? age.Value : 0;
원래 코드 :
void f(SomeType s)
{
if (s == null)
{
throw new ArgumentNullException("s cannot be null.");
}
// Use s
}
다음과 같이 다시 작성하십시오.
void f(SomeType s)
{
if (s == null) throw new ArgumentNullException(nameof(s));
}
[편집] 사용하여 다시 작성하는 이유 nameof
는 쉽게 리팩토링 할 수 있기 때문입니다. 변수 이름이 s
변경되면 디버깅 메시지도 업데이트되는 반면 변수 이름을 하드 코딩하면 시간이 지남에 따라 업데이트 될 때 결국 구식이됩니다. 업계에서 사용되는 좋은 관행입니다.
참고 URL : https://stackoverflow.com/questions/7585493/null-parameter-checking-in-c-sharp
'ProgramingTip' 카테고리의 다른 글
버튼에 그림자를 제공하는 방법 (0) | 2020.10.20 |
---|---|
epoll, poll, threadpool의 차이점은 무엇입니까? (0) | 2020.10.20 |
점선 (0) | 2020.10.20 |
PostgreSQL 서버가 중지되지 않았습니다 (0) | 2020.10.20 |
Java 9에서 sdkmanager --list (Android SDK) 실행 실패 (0) | 2020.10.20 |