이것은 ?[]? C #의 구문?


85

나는 공부하는 동안 대표 추상 클래스가 실제로을 Delegate.cs, 나는 다음과 같은 방법이있는 이해가 안보고

  • 반환 값 ?이 이미 reference ( class ) 유형 이지만 왜 값을 사용합니까?
  • ?[]? 매개 변수에 대한 의미

설명해 주시겠습니까?

public static Delegate? Combine(params Delegate?[]? delegates)
{
    if (delegates == null || delegates.Length == 0)
        return null;

    Delegate? d = delegates[0];
    for (int i = 1; i < delegates.Length; i++)
        d = Combine(d, delegates[i]);

    return d;
}


23
nullable 값을 포함 할 수있는 nullable 배열입니까?
Cid

3
c # 8, 이제 객체 변수가 null이 될 수 없도록 지정할 수 있습니다. 당신이 컴파일러 플래그를 플립하면 모든 변수를 지정해야 한다 null이 될 수 있습니다.
Jeremy Lakeman

답변:


66

단계별 설명 :

params Delegate?[] delegates -nullable 배열입니다 Delegate

params Delegate?[]? delegates -전체 배열은 널 입력 가능

각 매개 변수는 유형 Delegate?이고 Delegate?[]?배열 의 색인을 리턴하므로 리턴 유형이 Delegate?그렇지 않으면 컴파일러는 마치 마치 마치 마치 int문자열을 리턴하는 메소드에서 와 같이 오류 를 리턴합니다.

예를 들어 다음 Delegate과 같은 유형 을 반환하도록 코드를 변경할 수 있습니다 .

public static Delegate Combine(params Delegate?[]? delegates)
{
    Delegate defaulDelegate = // someDelegate here
    if (delegates == null || delegates.Length == 0)
        return defaulDelegate;

    Delegate d = delegates[0] ?? defaulDelegate;
    for (int i = 1; i < delegates.Length; i++)
        d = Combine(d, delegates[i]);

    return d;
}

4
첫 번째 질문은 어떻습니까? 반환 값 ?이 이미 참조 (클래스) 유형이지만 왜 사용합니까?
snr-Reinstate Monica

2
델리게이트 인 d를 반환하기 때문에? 유형. 또한 null 또는 위임은 매개 변수에 따라
아타나시오 Kataras에게

2
@snr 반환 값은 ?인수 값이를 사용하는 이유와 정확히 동일한 이유로를 사용합니다 ?. 후자를 이해하면 자동으로 전자를 이해합니다. 매개 변수 가 null을 허용 하는 것처럼 메서드 는 null을 반환 할 수 있습니다 . 즉, 둘 다 null을 포함 할 수 있습니다 .
GSerg

2
나는 그것을 만졌다. 예를 들어 두 번째 부분으로 대답했습니다. Since each parameter is of the type Delegate? and you return an index of the Delegate?[]? array, then it makes sense that the return type is Delegate?
Athanasios Kataras

2
@ snr : 왜 반환 값이 사용됩니까? 이미 참조 (클래스) 유형이지만 (1) 비슷한 코드에서 구조체를 사용하는 경우 습관이나 리팩토링 잔재 일 수 있습니다 (2) C # 8에서 참조 유형은 본질적으로 null을 허용하지 않을 수 있습니다 (따라서 명시적인 null 허용이 필요합니다 ( 3) Foo?깔끔한 HasValue속성 Foo을 가지고 있지만 == null확인이 필요하다. (4) null이 가능하고, 예상되고, 정확한 결과라는 메소드 서명을 읽는 개발자에게 전달한다. (5) 코드는 누군가가 작성한 것으로 보인다
무효를

25

널 입력 가능 참조 유형 은 C # 8.0의 새로운 기능이며 이전에는 존재하지 않았습니다.

문서화 문제이며 컴파일 타임에 경고가 생성되는 방식입니다.

"객체가 객체의 인스턴스로 설정되지 않았습니다"예외는 일반적입니다. 그러나 이것은 런타임 예외이며 컴파일 타임에 부분적으로 이미 발견 될 수 있습니다.

규제 Delegate d를 위해 당신은 항상 전화 할 수 있습니다

 d.Invoke();

즉, 컴파일 타임에 아무 일도 일어나지 않을 수 있습니다. 런타임에 예외가 발생할 수 있습니다.

새로운 Delegate? p이 코드 동안

 p.Invoke();

컴파일러 경고를 생성합니다. CS8602: Dereference of a possibly null reference 당신이 쓰지 않으면 :

 p?.Invoke();

의미하는 것은 null이 아닌 경우에만 호출하십시오.

따라서 변수에 null을 포함하거나 포함하지 않을 수 있음을 문서화하십시오. 조기에 경고를 발생 시키며 null에 대한 여러 테스트를 피할 수 있습니다. 당신은 int와 int에 대해 무엇을 가지고 있습니까?. 당신은 확실히 하나는 null이 아니며 하나를 다른 것으로 변환하는 방법을 알고 있습니다.


당신이 확실하지 않은 경고와 함께 그것은 Delegatenull이 아닙니다. 당신은 당신이 확실히 알고있는 척합니다 (대부분의 경우에 충분합니다).
Tim Pohlmann

@TimPohlmann int i = null뿐만 아니라 문자열 s = null도 불가능합니다 (이 주요 변경 사항이있는 C # 8에서는). 그래서 뭔가를 가장하는 것 이상입니다. 이전 버전과의 호환성을 위해 경고로 다운 그레이드되었습니다. 경고를 오류로 업그레이드하면 null이 아닌지 알 수 있습니다.
Holger

4
지난번에 NRT를 확인한 것은 100 % 방탄이 아닙니다. 컴파일러가 감지 할 수없는 특별한 경우가 있습니다.
Tim Pohlmann 2014

예. 그러나 "변수가 초기화되지 않았습니다"또는 "값을 반환하는 모든 코드 경로가 아님"경고와 동일합니다. 이는 런타임에 감지하지 않고 100 % 컴파일 타임 기능입니다. int?와 달리 추가 정보를 보유하기 위해 메모리를 추가하지 않는다고 생각합니다. 인텔리전스만큼 신뢰할 만하다고 가정 해 봅시다. 꽤 좋아요
Holger

1
가 있으면 intnull이 될 수 없습니다. 당신이 Delegate그것을 가지고 있다면 , 널 (null) 일 수 있습니다 (예를 들어 리플렉션과 같은 다양한 이유로). 일반적으로 Delegate(NRT가 활성화 된 C # 8)이 null이 아니라고 확신하는 것은 안전합니다 (확실히 알 수있는 곳 int).
Tim Pohlmann

5

C # 8에서는 참조 유형을 명시 적으로 널 입력 가능으로 표시해야합니다.

기본적으로 이러한 유형은 값 유형과 비슷한 null을 포함 할 수 없습니다. 이것은 후드 아래에서 작동하는 방식을 변경하지 않지만 유형 검사기는 수동으로 수행해야합니다.

주어진 코드는 C # 8에서 작동하도록 리팩토링되었지만이 새로운 기능의 이점은 없습니다.

public static Delegate? Combine(params Delegate?[]? delegates)
{
    // ...[]? delegates - is not null-safe, so check for null and emptiness
    if (delegates == null || delegates.Length == 0)
        return null;

    // Delegate? d - is not null-safe too
    Delegate? d = delegates[0];
    for (int i = 1; i < delegates.Length; i++)
        d = Combine(d, delegates[i]);

    return d;
}

다음은이 기능을 활용하는 업데이트 된 코드 (작동하지 않음, 아이디어)의 예입니다. 그것은 널 체크에서 우리를 구하고이 방법을 약간 단순화했습니다.

public static Delegate? Combine(params Delegate[] delegates)
{
    // `...[] delegates` - is null-safe, so just check if array is empty
    if (delegates.Length == 0) return null;

    // `d` - is null-safe too, since we know for sure `delegates` is both not null and not empty
    Delegate d = delegates[0];

    for (int i = 1; i < delegates.Length; i++)
        // then here is a problem if `Combine` returns nullable
        // probably, we can add some null-checks here OR mark `d` as nullable
        d = Combine(d, delegates[i]);

    return d;
}

2
those types are not able to contain null오류가 아닌 컴파일러 경고를 생성합니다 . 코드는 NullReferenceExceptions를 생성 할 수 있지만 정상적으로 실행됩니다. 이는 이전 버전과의 호환성을 염두에두고 수행됩니다.
JAD
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.