Нульовий посилальний тип у C # 8 при використанні класів DTO з ORM


9

Я активував цю функцію в проекті з класами об'єктів передачі даних (DTO), як зазначено нижче:

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

Але я отримую помилку:

CS8618: Незмінна властивість "ServiceUrl" неініціалізована. Поміркуйте, визнавши властивість недійсною.

Це клас DTO, тому я не ініціалізую властивості. Це буде відповідальність за код ініціалізації класу, щоб переконатися, що властивості не є нульовими.

Наприклад, абонент може зробити:

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

Моє запитання: Як поводитися з такими помилками в класах DTO, коли ввімкнено контекст зворотності C # 8?


3
Коли ви робите ініціалізацію побудови так, як ви показуєте, конструктор за замовчуванням запускається (ініціалізуючи ServiceUrl до його значення за замовчуванням (що для рядків є нульовим)). Потім запускається оператор ініціалізації. Якщо ви хочете, щоб це не було нульовим, йому потрібно вийти з усіх ініціалізованих конструкторів
Flydog57

POCO не означає, що він не має конструктора або що властивості не ініціалізуються. Це означає Plain Old C# Object. Просто об’єкт, як і будь-який інший, без успадкування від якогось спеціального класу. Я підозрюю, що у вас інше питання. Як створити DTO -Data Transfer Objects
Panagiotis Kanavos

This should be the responsibility of the one initializing the class to ensure that the properties are non-nullклас повинен бути у дійсному стані завжди. Якщо nullце не дозволено, властивість ніколи не має бути нульовим. Можливо, замість базового рядка слід використовувати спеціалізований клас для URL-адреси, який може мати значення або None`Відсутній`, як клас Option у F #. C # 8 дозволяє писати такі класи та перевіряти їх за відповідності шаблону
Панайотис Канавос

@ Panagiotis Kanavos, Клас, у моєму випадку, має обмеження бути конструктором без параметрів. Так що я повинен використовувати властивість Initializer: public string ServiceUrl { get; set; } = default! ;. Я сподіваюся, що в майбутньому Рослін може мати спосіб вирішити пізню ініціалізацію поза сферою ctor. Я використовував MayBe <T> (як клас Option), але я перейшов на нульовий опорний тип в c # 8 для нового коду.
М.Гассан

НЗТ не є Maybes, насправді, Maybes тепер ще більш важливо і простіше у використанні. Звичайно, вони створюють за допомогою ідіом C #, які полегшують роботу з узгодженням шаблону
Panagiotis Kanavos

Відповіді:


9

Наступне рішення рекомендується EF Core & 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));
        }


У запитанні було зазначено, що він не може використовувати !оператора.
Атанасіос Катарас

Я не можу використовувати! з типом, але вказане нами посилання показує, як ініціалізувати за допомогою null !. Це рішення рішення. Я змінив питання.
М.Гассан

8

Якщо це не нульове значення, то що може робити компілятор, коли об'єкт ініціалізується?

Значення за замовчуванням рядка є нульовим, тому ви будете

  1. або потрібно присвоїти рядкові значення за замовчуванням у декларації

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

  2. Або ініціалізуйте значення в конструкторі за замовчуванням, щоб ви позбулися від попередження

  3. Використовувати ! оператора (який ви не можете використовувати)

  4. Зробіть його незмінним, як згадується robbpriestley.


4
Або, звичайно, додайте конструктор, що приймає URL-адресу служби як ненульовий рядок.
Джон Скіт

ServiceUrl'не може бути = String.Empty. Є й інші Властивості складного типу, які не можуть бути нульовими, тому я використовував, defaultяк: 'public MyClass MyProperty {get; набір; } = за замовчуванням! ', щоб припинити попередження. Цей клас (та інші) є конструктором без параметрів і останнім часом ініціалізується поза сферою ctor.
М.Гассан

0

Ще одна річ, яка може стати в нагоді в деяких сценаріях:

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

Може використовуватися поверх члена або цілого типу.


Ще одна річ, яку слід врахувати - додавання #nullable disableзверху до файлу, щоб вимкнути нульову посилання для всього файлу.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.