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.