Development Tip

ArgumentNullException 던지기

yourdevel 2020. 12. 10. 21:21
반응형

ArgumentNullException 던지기


어떤 종류의 객체를 인수로 취하는 메서드가 있다고 가정 해 보겠습니다. 이제이 메서드에 null 인수가 전달되면 치명적인 오류이며 예외가 발생해야합니다. 다음과 같이 코딩 할 가치가 있습니까? (이것이 사소한 예임을 명심하십시오) :

void someMethod(SomeClass x)
{
    if (x == null){
        throw new ArgumentNullException("someMethod received a null argument!");
    }

    x.doSomething();
}

아니면 x.doSomething ()을 호출 할 때 NullException을 던지는 것에 의존하는 것이 안전합니까?

둘째, someMethod가 생성자이고 다른 메서드가 호출 될 때까지 x가 사용되지 않는다고 가정합니다. 즉시 예외를 throw해야합니까? 아니면 x가 필요할 때까지 기다렸다가 예외를 throw해야합니까?


나는 인수를 확인하지 않는 것이 제공 하는 것 ArgumentNullException보다 선호합니다 NullReferenceException. 일반적으로 내 선호는 잠재적으로 null 개체에 대한 메서드를 호출하기 전에 항상 nullity를 확인하는 것입니다.

메서드가 생성자 인 경우 몇 가지 다른 요인에 따라 달라집니다. 속성에 대한 공개 설정기도 있고 개체가 실제로 사용될 가능성이 얼마나되는지 여부입니다. 공용 setter가있는 경우 생성자를 통해 유효한 인스턴스를 제공하지 않는 것이 합리적이며 예외가 발생하지 않아야합니다.

공용 setter가없고 삽입 된 개체에 대한 참조없이 포함 개체를 사용할 수있는 경우 사용을 시도 할 때까지 검사 / 예외를 연기 할 수 있습니다. 하지만 일반적인 경우는 주입 된 객체가 인스턴스의 기능에 필수적이며 따라서 인스턴스가 그것 없이는 작동 할 수 없기 때문에 ArgumentNull 예외가 완벽하게 합리적이라고 생각합니다.


나는 항상 빠른 실패 의 관행을 따릅니다 . 메서드가 X에 종속되고 X가 null로 전달 될 수 있음을 이해하는 경우 null을 확인하고 실패 지점을 연장하는 대신 즉시 예외를 발생시킵니다.

2016 년 업데이트 :

실제 사례. Jetbrains Annotations 사용을 적극 권장합니다 .

[Pure]
public static object Call([NotNull] Type declaringType, 
                          [NotNull] string methodName, 
                          [CanBeNull] object instance)
{
    if (declaringType == null) throw new ArgumentNullException(nameof(declaringType));
    if (methodName == null) throw new ArgumentNullException(nameof(methodName));

Guard 문은 nameof연산자를 제공하는 C # 6을 통해 크게 향상되었습니다 .


다음과 같은 이유로 명시적인 예외를 선호합니다.

  • 메서드에 둘 이상의 SomeClass 인수가있는 경우 어떤 인수인지 말할 수있는 기회를 제공합니다 (다른 모든 것은 호출 스택에서 사용할 수 있음).
  • x를 참조하기 전에 부작용이있을 수있는 일을하면 어떨까요?

나는 빨리 실패한다는 생각에 동의합니다. 그러나 빠른 실패가 왜 실용적인지 아는 것이 현명합니다. 이 예를 고려하십시오.

void someMethod(SomeClass x)
{       
    x.Property.doSomething();
}

에 의존하여 NullReferenceException무언가 잘못되었다고 말하면 null이 무엇인지 어떻게 알 수 있습니까? 스택 추적은 어떤 참조가 null이 아닌 줄 번호 만 제공합니다. 이 예에서 x또는 x.Property둘 다 null 일 수 있고 사전에 적극적인 검사를 통해 빠르게 실패하지 않으면 그것이 무엇인지 알 수 없습니다.


또한 명시적인 ArgumentNullException을 사용하여 매개 변수 검사를 선호합니다.

메타 데이터 살펴보기 :

 //
    // Summary:
    //     Initializes a new instance of the System.ArgumentNullException class with
    //     the name of the parameter that causes this exception.
    //
    // Parameters:
    //   paramName:
    //     The name of the parameter that caused the exception.
    public ArgumentNullException(string paramName);

문자열이 매개 변수의 이름, 즉 null이어야한다는 것을 알 수 있으므로 개발자에게 무엇이 잘못되었는지에 대한 힌트를 제공합니다.


ArgumentNullException을 더 빨리 던지는 것이 좋습니다. 던지면 NullReferenceException보다 문제에 대한 더 유용한 정보를 제공 할 수 있습니다.


입력이 null이 아닐 것으로 예상하는 경우 ArgumentNullException을 명시 적으로 throw해야합니다. 이를위한 도우미 메서드를 제공하는 Guard라는 클래스를 작성할 수 있습니다. 따라서 코드는 다음과 같습니다.

void someMethod(SomeClass x, SomeClass y)
{
    Guard.NotNull(x,"x","someMethod received a null x argument!");
    Guard.NotNull(y,"y","someMethod received a null y argument!");


    x.doSomething();
    y.doSomething();
}

NonNull 메서드는 nullity 검사를 수행하고 호출에 지정된 오류 메시지와 함께 NullArgumentException을 throw합니다.


1- Null 값을 원하지 않으면 명시 적으로 수행하십시오. 그렇지 않으면 다른 사람이 코드를 볼 때 Null 값을 전달하는 것이 허용된다고 생각할 것입니다.

2- 할 수있는 한 더 빨리하십시오. 이렇게하면 예상되지 않은 Null을 갖는 "잘못된"동작을 전파하지 않습니다.


If you program defensively you should fail fast. So check your inputs and error out at the beginning of your code. You should be nice to your caller and give them the most descriptive error message you can.


I'll probably be downvoted for this, but I think completely different.

What about following a good practice called "never pass null" and remove the ugly exception checking?

If the parameter is an object, DO NOT PASS NULL. Also, DO NOT RETURN NULL. You can even use the Null object pattern to help with that.

If it's optional, use default values (if your language supports them) or create an overload.

Much cleaner than ugly exceptions.


You can use syntax like the following to not just throw an ArgumentNullException but have that exception name the parameter as part of its error text as well. E.g.;

void SomeMethod(SomeObject someObject)
{
    Throw.IfArgNull(() => someObject);
    //... do more stuff
}

The class used to raise the exception is;

public static class Throw
{
    public static void IfArgNull<T>(Expression<Func<T>> arg)
    {
        if (arg == null)
        {
            throw new ArgumentNullException(nameof(arg), "There is no expression with which to test the object's value.");
        }

        // get the variable name of the argument
        MemberExpression metaData = arg.Body as MemberExpression;
        if (metaData == null)
        {
            throw new ArgumentException("Unable to retrieve the name of the object being tested.", nameof(arg));
        }

        // can the data type be null at all
        string argName = metaData.Member.Name;
        Type type = typeof(T);
        if (type.IsValueType && Nullable.GetUnderlyingType(type) == null)
        {
            throw new ArgumentException("The expression does not specify a nullible type.", argName);
        }

        // get the value and check for null
        if (arg.Compile()() == null)
        {
            throw new ArgumentNullException(argName);
        }
    }
}

참고URL : https://stackoverflow.com/questions/368742/throwing-argumentnullexception

반응형