[C#] C # 4.0 : TimeSpan을 기본값을 가진 선택적 매개 변수로 사용할 수 있습니까?

이 두 가지 모두 컴파일 타임 상수 여야한다는 오류를 생성합니다.

void Foo(TimeSpan span = TimeSpan.FromSeconds(2.0))
void Foo(TimeSpan span = new TimeSpan(2000))

우선 누군가 컴파일 타임에 이러한 값을 결정할 수없는 이유를 설명 할 수 있습니까? 그리고 선택적인 TimeSpan 객체의 기본값을 지정하는 방법이 있습니까?



답변

서명을 변경하면이 문제를 매우 쉽게 해결할 수 있습니다.

void Foo(TimeSpan? span = null) {

   if (span == null) { span = TimeSpan.FromSeconds(2); }

   ...

}

자세히 설명해야합니다-예제의 표현식이 컴파일 타임 상수가 아닌 이유는 컴파일 타임에 컴파일러가 TimeSpan.FromSeconds (2.0)을 실행하고 결과 바이트를 컴파일 된 코드에 넣을 수 없기 때문입니다.

예를 들어 DateTime.Now를 대신 사용하려고했는지 고려하십시오. DateTime.Now의 값은 실행될 때마다 변경됩니다. 또는 TimeSpan.FromSeconds가 중력을 고려했다고 가정하십시오. 터무니없는 예제이지만 컴파일 타임 상수 규칙은 TimeSpan.FromSeconds가 결정적이라는 것을 알기 때문에 특별한 경우를 만들지 않습니다.


답변

내 VB6 유산은 “널 값”과 “결측 값”을 동등한 것으로 간주한다는 생각으로 인해 불편합니다. 대부분의 경우 문제는 없지만, 의도하지 않은 부작용이 있거나 예외적 인 조건을 삼킬 수 있습니다 (예 : 소스 span가 null이 아니어야하지만 속성이 아닌 속성 또는 변수 인 경우).

따라서 메서드를 오버로드합니다.

void Foo()
{
    Foo(TimeSpan.FromSeconds(2.0));
}
void Foo(TimeSpan span)
{
    //...
}


답변

이것은 잘 작동합니다 :

void Foo(TimeSpan span = default(TimeSpan))


답변

기본값으로 사용할 수있는 값 세트는 속성 인수에 사용할 수있는 것과 같습니다. 기본값이의 내부 메타 데이터로 인코딩되기 때문 DefaultParameterValueAttribute입니다.

컴파일 타임에 결정할 수없는 이유에 관해서. 컴파일 타임에 허용되는 값에 대한 값과 표현식은 공식 C # 언어 사양에 나열되어 있습니다 .

C # 6.0-속성 매개 변수 유형 :

속성 클래스의 위치 및 명명 된 매개 변수 유형은 다음과 같은 속성 매개 변수 유형으로 제한됩니다 .

  • 다음 유형 중 하나 : bool, byte, char, double, float, int, long, sbyte, short, string, uint, ulong, ushort.
  • 유형 object입니다.
  • 유형 System.Type입니다.
  • 열거 형입니다.
    (공개 접근성 및 중첩 유형 (있는 경우)도 공개 접근성 제공)
  • 위 유형의 1 차원 배열.

유형 TimeSpan은 이러한 목록에 맞지 않으므로 상수로 사용할 수 없습니다.


답변

void Foo(TimeSpan span = default(TimeSpan))
{
    if (span == default(TimeSpan))
        span = TimeSpan.FromSeconds(2);
}

제공된 default(TimeSpan)함수에 유효한 값이 아닙니다.

또는

//this works only for value types which TimeSpan is
void Foo(TimeSpan span = new TimeSpan())
{
    if (span == new TimeSpan())
        span = TimeSpan.FromSeconds(2);
}

제공된 new TimeSpan()값이 유효하지 않습니다.

또는

void Foo(TimeSpan? span = null)
{
    if (span == null)
        span = TimeSpan.FromSeconds(2);
}

null값이 함수에 유효한 값일 가능성 이 희박하다는 점을 고려하면 더 좋습니다 .


답변

TimeSpan의 특별한 경우이며 메소드 DefaultValueAttribute를 통해 구문 분석 할 수있는 문자열을 사용하여 지정됩니다 TimeSpan.Parse.

[DefaultValue("0:10:0")]
public TimeSpan Duration { get; set; }


답변

나의 제안:

void A( long spanInMs = 2000 )
{
    var ts = TimeSpan.FromMilliseconds(spanInMs);

    //...
}

BTW
TimeSpan.FromSeconds(2.0)가 같지 않음 new TimeSpan(2000)-생성자가 틱을 걸립니다.