ORM과 함께 DTO 클래스를 사용할 때 C # 8의 널 입력 가능 참조 유형


9

아래와 같이 DTO (Data Transfer Object) 클래스가있는 프로젝트에서이 기능을 활성화했습니다.

public class Connection
    {
        public string ServiceUrl { get; set; }
        public string? UserName { get; set; }
        public string? Password { get; set; }
        //... others 
    }

하지만 오류가 발생합니다.

CS8618: 널 입력 불가능 특성 'ServiceUrl'이 초기화되지 않았습니다. 속성을 nullable로 선언하십시오.

이것은 DTO 클래스이므로 속성을 초기화하지 않습니다. 이 속성은 null이 아닌지 확인하기 위해 클래스를 초기화하는 코드의 책임입니다.

예를 들어, 발신자는 다음을 수행 할 수 있습니다.

var connection = new Connection
{
  ServiceUrl=some_value,
  //...
}

내 질문 : C # 8의 nullability 컨텍스트가 활성화되어있을 때 DTO 클래스에서 이러한 오류를 처리하는 방법은 무엇입니까?


3
표시하는 방식으로 구성 초기화를 수행하면 기본 생성자가 실행됩니다 (ServiceUrl을 기본값 (문자열의 경우 null)으로 초기화). 그런 다음 initialize 문이 실행됩니다. null을 허용하지 않으려면 초기화 된 모든 생성자를 종료해야합니다.
Flydog57

POCO는 생성자가 없거나 속성이 초기화되지 않았다는 것을 의미하지 않습니다. 의미 Plain Old C# Object합니다. 특별한 클래스에서 상속받지 않고 다른 객체처럼. 다른 질문 이 있다고 생각합니다 . - DTO들 만드는 방법Data Transfer Objects
파나지오티스 Kanavos

This should be the responsibility of the one initializing the class to ensure that the properties are non-null클래스는 항상 유효한 상태 여야합니다. null허용되지 않는 경우 속성은 null 이 아니 어야합니다 . 아마도 기본 문자열 대신 NoneF #의 Option 클래스와 같이 값이 없거나 누락 된 URL에 특수 클래스를 사용해야합니다 . C # 8은 같은 클래스를 작성하고 패턴 매칭로를 확인할 수 있습니다
파나지오티스 Kanavos

@Panagiotis Kanavos, 필자의 경우 클래스에는 매개 변수가없는 생성자가되어야합니다. 그래서 Property Initializer를 사용해야합니다 : public string ServiceUrl { get; set; } = default! ;. Roslyn이 앞으로 ctor의 범위 밖에서 늦은 초기화를 처리하는 방법을 가질 수 있기를 바랍니다. 옵션 클래스와 같은 MayBe <T>를 사용하고 있었지만 새 코드를 위해 c # 8에서 nullable Reference Type으로 전환했습니다.
M.Hassan

NRT는 사실은 아닙니다. 사실, 이제는 가능성이 훨씬 중요하고 사용하기 쉽습니다. 그들은 패턴 매칭 쉽게 작업을 할 C #을 숙어 빌드 사용하고 물론 제공
파나지오티스 Kanavos을

답변:


9

다음 솔루션은 EF 코어 및 EF6 추천 참조

1) null!용서 연산자 로 초기화하여

public string ServiceUrl { get; set; } = null! ;
//or
public string ServiceUrl { get; set; } = default! ;

2) 백업 필드 사용 :

        private string _ServiceUrl;
        public string ServiceUrl
        {
            set => _ServiceUrl = value;
            get => _ServiceUrl
                   ?? throw new InvalidOperationException("Uninitialized property: " + nameof(ServiceUrl));
        }


문제는 그가 !연산자를 사용할 수 없다고 언급했습니다 .
Athanasios Kataras

사용할 수 없습니다! 유형이 있지만 언급 한 링크는 null!을 사용하여 초기화하는 방법을 보여줍니다. 해결 방법입니다. 질문을 수정했습니다.
M.Hassan

8

nullable이 아닌 경우 객체가 초기화 될 때 컴파일러가 수행 할 수있는 작업은 무엇입니까?

문자열의 기본값은 null이므로

  1. 선언에서 문자열 기본값을 할당해야합니다.

    public string ServiceUrl { get; set; } = String.Empty;

  2. 또는 기본 생성자에서 값을 초기화하여 경고를 제거하십시오.

  3. !연산자를 사용하십시오 (사용할 수 없음)

  4. robbpriestley가 언급했듯이 null을 허용하십시오.


4
또는 서비스 URL을 널 입력 불가능 문자열로 승인하는 생성자를 추가하십시오.
Jon Skeet

ServiceUrl'= String.Empty 일 수 없습니다. null이 될 수없는 복잡한 유형의 다른 속성이 있으므로 다음 default과 같이 사용했습니다 . 'public MyClass MyProperty {get; 세트; } = 기본! 경고를 중지합니다. 이 클래스 (및 기타 클래스)는 매개 변수가없는 생성자이며 최근 ctor의 범위 밖에서 초기화됩니다.
M.Hassan

0

일부 시나리오에서 유용한 또 다른 것은 :

[SuppressMessage("Compiler", "CS8618")]

멤버 또는 전체 유형 위에 사용할 수 있습니다.


고려해야 할 또 다른 사항은 #nullable disable전체 파일에 대해 nullable 참조를 비활성화하기 위해 파일 위에 추가 하는 것입니다.

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