메소드가 필드에서 실제로 널 점검임을 C # 널 입력 가능 참조에 알릴 수 있습니까?


14

다음 코드를 고려하십시오.

#nullable enable
class Foo
{
    public string? Name { get; set; }
    public bool HasName => Name != null;
    public void NameToUpperCase()
    {
        if (HasName)
        {
            Name = Name.ToUpper();
        }
    }
}

Name = Name.ToUpper ()에서 Name이 가능한 null 참조라는 경고가 표시됩니다. HasName을 인라인하여이 경고를 치료할 수 있으므로 조건은 if (Name! = null)입니다.

컴파일러에 HasName의 진정한 응답이 Name에 대해 null이 아닌 제약 조건을 암시한다고 지시 할 수있는 방법이 있습니까?

HasName이 실제로 훨씬 더 많은 것을 테스트 할 수 있기 때문에 중요하며 여러 곳에서 사용하거나 API 표면의 공개 부분이 될 수 있습니다. null 검사를 자체 방법으로 인수 화해야하는 많은 이유가 있지만 그렇게하면 nullable 참조 검사기가 깨지는 것 같습니다.


1
IMO HasValue는 nullable 유형을 사용해야 하며 검사하지 마십시오 null. 그래도 문제에 영향을 미치지 않습니다.
프레드릭

난 당신이 경우에, 당신이 당신의 코드를 포장 할 수 있다고 생각 #nullable disable다음 #nullable enable또는 restore(나중에 다시 docs.microsoft.com/en-us/dotnet/csharp/... ).
GaryNg

5
"dammit" !연산자를 사용할 수 있습니다 . if(HasName) { Name = Name!.ToUpper(); }
Jan Paolo Go

1
다중 스레드 응용 프로그램의 경우 속성으로 돌아 가지 않고 로컬로 변수를 사용하여 HasName 검사 후 Name이 null이 될 수 있습니다 (게터에서 속성이 수행 할 수 있음을 알고 있음). 많은 일이 발생한 이벤트 핸들러 사용)
XIU

답변:


3

나는 다른 속성을 둘러 보았고 System.Diagnostics.CodeAnalysis적용 가능한 것을 찾을 수 없었습니다. 매우 실망 스럽습니다. 원하는 것에 가장 가까운 것은 다음과 같습니다.

public bool TryGetName([NotNullWhen(true)] out string? name)
{
    name = Name;
    return name != null;
}

public void NameToUpperCase()
{
    if (TryGetName(out var name))
    {
        Name = name.ToUpper();
    }
}

꽤 번거로워 보입니다. nullable 속성대해서는 MSDN 문서를 참조하십시오 . 아마도 더 깔끔한 것을 찾을 수 있습니다.


2
우리는 더 많은 속성이나 typescript의 주장과 같은 것이 필요해 보입니다
Stilgar

제가이 질문을 답으로 고를 것입니다. 왜냐하면 제가 두려워했던 것처럼 실제 대답은 "아니오, c #은 아직 그렇게하지 않습니다."
John Melville

@ JohnMelville 나는 그러한 기능에 대한 제안도 찾을 수 없었기 때문에 곧이 변화를 기대할 수 있다고 생각하지 않습니다.
V0ldek

2
@XIU 컴파일러는이 측면에서 이미 느슨합니다. 그렇게하면 if(Name != null) return Null.ToUpper()기술적으로 TOCTOU 경쟁 조건이지만 null 역 참조에 대한 경고가 없습니다. Mads Torgersen이 어떻게 그것을 고려했는지에 대해 말한 것을 기억하지만 nullable 참조 유형 기능 전체가 실제로 쓸모가 없을 정도로 많은 오탐을 생성합니다. 다른 스레드가 속성을 변경하지 않는 시간의 99 %. 따라서이 속성에 대한 검사를 다른 속성에 대한 null 검사로 취급하는 속성을 만드는 것만으로도 충분합니다.
V0ldek

2
"이 제안을 찾을 수 없습니다"문제를 해결했습니다. ( github.com/dotnet/csharplang/issues/2997 ) 행운을 빌어주세요.
John Melville

-10

문자열은 참조 형식이며 nullable (예 int?:)은 nullable 값 형식입니다. 그래서 당신은 정말로 이것을 할 수 없습니다 string? myString; 필요한 것은 이것입니다.

class Foo
{
    public string Name { get; set; }
    public bool HasName => !String.IsNullOrEmpty(Name);  ////assume you want empty to be treated same way as null
    public void NameToUpperCase()
    {
        if (HasName)
        {
            Name = Name.ToUpper();
        }
    }
}

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.