마술 숫자보다 nullable 유형이 선호됩니까? C #을

요즘 동료와 약간의 토론이있었습니다. 우리는 구체적으로 C #을 사용하고 있지만 이것은 nullable 타입을 가진 모든 언어에 적용될 수 있습니다. 예를 들어 최대 값을 나타내는 값이 있다고 가정하십시오. 그러나이 최대 값은 선택 사항입니다. 나는 nullable 숫자가 바람직하다고 주장한다. 내 동료는 선례를 인용하여 0을 사용하는 것을 선호합니다. 물론, 네트워크 소켓과 같은 것들은 종종 0을 사용하여 무제한 시간 초과를 나타냅니다. 오늘 소켓을 다루는 코드를 작성하려면 시간 초과가 없다는 사실을 더 잘 나타낼 것이라고 생각하기 때문에 개인적으로 nullable 값을 사용합니다.

어느 표현이 더 낫습니까? 둘 다 “없음”을 의미하는 값을 확인하는 조건이 필요하지만 nullable 유형은 의도를 조금 더 잘 전달한다고 생각합니다.



답변

치다:

  • 언어,

  • 뼈대,

  • 문맥.

1. 언어

∞를 사용하면 최대한의 해결책이 될 수 있습니다.

  • 예를 들어, JavaScript에는 무한대가 있습니다. C #은 ¹이 아닙니다.

  • 예를 들어 Ada에는 범위가 있습니다. C #은 그렇지 않습니다.

C #에는가 int.MaxValue있지만 귀하의 경우에는 사용할 수 없습니다. int.MaxValue최대 정수 2,147,483,647입니다. 코드에서 2,147,483,647을 사용하는 것은 폭발하기 전에 최대 허용 압력과 같이 최대 값을 가진 경우 의미가 없습니다.

2. 프레임 워크

.NET Framework는이 시점에서 다소 일관성이 없으며 마법 값의 사용을 비판 할 수 있습니다.

예를 들어, "Hello".IndexOf("Z")매직 값을 반환합니다 -1. 그것은 어쩌면 그것 (그것을합니까?) 쉽게 결과를 조작하기 위해 :

int position = "Hello".IndexOf("Z");
if (position > 0)
{
    DoSomething(position);
}

사용자 정의 구조를 사용하는 대신

SearchOccurrence occurrence = "Hello".IndexOf("Z");
if (occurrence.IsFound)
{
    DoSomething(occurrence.StartOffset);
}

그러나 전혀 직관적이지 않습니다. 왜 -1그렇지 -123않습니까? 초보자도 실수로 0“찾을 수 없음” 을 의미 한다고 생각 하거나 잘못 입력 할 수 있습니다.(position >= 0) .

3. 맥락

코드가 네트워크 소켓의 시간 초과와 관련이 있다면 일관성을 위해 수십 년 동안 모든 사람이 사용한 것을 사용하는 것은 나쁜 생각이 아닙니다 . 특히 0시간 초과가 매우 명확하다는 것은 0이 될 수없는 값입니다. 이 경우 사용자 정의 클래스를 사용하면 상황을 이해하기가 더 어려워 질 수 있습니다.

class Timeout
{
    // A value indicating whether there is a timeout.
    public bool IsTimeoutEnabled { get; set; }

    // The duration of the timeout, in milliseconds.
    public int Duration { get; set; }
}
  • 설정할 수 있습니까 DurationIsTimeoutEnabledtrue이면 0으로 ?
  • 경우 IsTimeoutEnabled거짓, 무엇을 내가 설정하면 어떻게Duration (100)에?

여러 실수가 발생할 수 있습니다. 다음 코드를 상상해보십시오.

this.currentOperation.Timeout = new Timeout
{
    // Set the timeout to 200 ms.; we don't want this operation to be longer than that.
    Duration = 200,
};

this.currentOperation.Run();

작업이 10 초 동안 실행됩니다. Timeout수업 문서를 읽지 않고이 코드의 문제점을 볼 수 있습니까 ?

결론

  • null여기에 가치가 없다는 아이디어를 잘 표현합니다. 제공되지 않습니다. 사용할 수 없습니다. 숫자도 아니고 0 / 빈 문자열도 아닙니다. 최대 값 또는 최소값으로 사용하지 마십시오.

  • int.MaxValue언어 자체와 밀접한 관련이 있습니다. 클래스 int.MaxValue의 최대 속도 제한 Vehicle또는 항공기 등의 최대 허용 속도 에는 사용하지 마십시오 .

  • -1코드에서 와 같이 마법의 값을 피하십시오 . 그들은 오도의 소지가 있으며 코드의 실수로 이어집니다.

  • 최소값 / 최대 값을 지정하여보다 직관적 인 클래스를 직접 만듭니다. 예를 VehicleSpeed들어을 가질 수 있습니다 VehicleSpeed.MaxValue.

  • 이 분야에서 코드를 작성하는 대부분의 사람들이 사용하는 매우 구체적인 분야에서 수십 년 동안 일반적인 관례라면 이전 지침을 따르지 않고 마법의 가치를 사용하십시오.

  • 접근 방식을 혼합하는 것을 잊지 마십시오. 예를 들면 다음과 같습니다.

    class DnsQuery
    {
        public const int NoTimeout = 0;
    
        public int Timeout { get; set; }
    }
    
    this.query.Timeout = 0; // For people who are familiar with timeouts set to zero.
    // or
    this.query.Timeout = DnsQuery.NoTimeout; // For other people.
    

¹ 무한대를 포함한 고유 한 유형을 만들 수 있습니다. 여기서는 기본 int유형에 대해서만 이야기하고 있습니다.


답변

널은 마법의 숫자보다 낫지 않습니다.

중요한 것은 마법의 효과가있는 값의 이름을 지정하고 그러한 값을 가져야하는 경우 해당 값의 정의가 마법의 가치와 wtf에 부딪 치는 사람이 볼 수있는 곳인지 확인하는 것입니다.

if (timeout == 4298435) ... // bad.
if (timeout == null) ... // bad.
if (timeout == NEVER_TIME_OUT) ... // yay! puppies and unicorns!


답변

MAGIC_NUMBER코드는 가능한 한 항상 피해야합니다. null보다 명확한 의도 표현입니다.


답변

C #에서 많은 CLR 클래스에는 정적 Empty멤버가 있습니다.

  • System.String.Empty
  • System.EventArgs.Empty
  • System.Guid.Empty
  • System.Drawing.Rectangle.Empty
  • System.Windows.Size.Empty

이렇게하면 빈 객체를 생성하기 위해 매직 값을 사용할지 아니면 null을 사용할지를 기억하지 않아도됩니다.

그러나 간단한 값 유형을 다루는 경우 int? 이 경우, 원시 강박 관념에 희생되는지 여부를 고려하십시오 . 명백히 단순한 숫자 속성이 자체 클래스 또는 구조체의 이점을 얻을 수 있으므로 Empty멤버 를 지정하고 해당 종류의 값에 고유 한 다른 동작을 추가 할 수 있습니다 .


답변

이 경우 널값은 최대 값이 없음을 나타내는 좋은 방법입니다. 일반적으로 특수한 경우에는 해당 값이 적용되지 않고 구성하는 기능을 원하지 않는 경우 null이 이에 대한 좋은 표시입니다.

특수한 경우를 나타내는 데 null을 사용할 때의 문제점은 하나의 null 값만 있고 여러 특수한 경우가있을 수 있다는 것입니다. 이 경우 특수한 경우를 나타내거나 int 값을 정상적으로 사용할 수있는 추가 매개 변수로 열거를 전달합니다. (이것은 본질적으로 Nullable <>이 당신을 위해하는 일이지만, 열거 형 대신 부울을 사용하고 매개 변수를 단일 구조로 결합합니다.)


답변

이 경우 nullable 유형이 완벽하다고 생각합니다.

Null은 가치가 없음을 의미합니다. 이것은 값이 0 인 숫자와는 분명히 다른 개념입니다.

“값을 제공하지 않으면 최대 값을 사용하십시오”라고 말하고 싶다면 null을 전달하는 것이 정확한 표현 방법입니다.


답변

널 (NULL) : 공통 오류 값, 지정되지 않음, 공백 또는 값 없음.

0 : 실제적이지만 반드시 논리적이거나 직관적 인 값은 아닙니다 (이 문맥에서). 초기화시 공통 값입니다.

문제의 맥락 timeoutInMilliseconds에서이 속성은 선택 사항이며이 방법의 오버 헤드로 인해 옵션으로 자격이 박탈 될 것이라는 언급은 없습니다.

결론 : 예외가 있으며 언어와 도메인에 따라 솔루션이 다릅니다. 이 경우 Null을 선택합니다. 일부 사람들 이이 잘못을 저지른 곳은 인터페이스와 데이터를 잘 분리하지 않은 경우입니다. 그들은 고객이 문서 (또는 구현)를 읽고 이러한 특수 값을 사용 / 처리하는 방법을 결정하기를 기대합니다. 특수 사례는 고객의 프로그램으로 유출되어 명확하지 않을 수 있습니다. 좋은 추상화 계층을 추가하면 사용법이 훨씬 명확해질 수 있습니다.