Jenis referensi yang tidak dapat dibatalkan dalam C # 8 saat menggunakan kelas DTO dengan ORM

9

Saya mengaktifkan fitur ini dalam proyek yang memiliki kelas objek transfer data (DTO), seperti yang diberikan di bawah ini:

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

Tapi saya mendapatkan kesalahan:

CS8618: Properti Non-nullable 'ServiceUrl' tidak diinisialisasi. Pertimbangkan menyatakan properti sebagai tidak dapat dibatalkan.

Ini adalah kelas DTO, jadi saya tidak menginisialisasi properti. Ini akan menjadi tanggung jawab kode yang menginisialisasi kelas untuk memastikan bahwa properti tidak nol.

Misalnya, pemanggil dapat melakukan:

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

Pertanyaan saya: Bagaimana menangani kesalahan seperti itu di kelas DTO ketika konteks nullability C # 8 diaktifkan?

M.Hassan
sumber
3
Ketika Anda melakukan inisialisasi konstruksi seperti yang Anda tunjukkan, konstruktor default berjalan (menginisialisasi ServiceUrl ke nilai defaultnya (yang, untuk string, adalah nol)). Kemudian, pernyataan inisialisasi berjalan. Jika Anda menginginkannya tidak dapat dibatalkan, ia harus keluar dari semua konstruktor yang diinisialisasi
Flydog57
POCO tidak berarti tidak memiliki konstruktor atau properti tidak diinisialisasi. Artinya Plain Old C# Object. Hanya objek seperti yang lain, tanpa mewarisi dari kelas khusus apa pun. Saya curiga Anda memiliki pertanyaan yang berbeda . Cara membuat DTO -Data Transfer Objects
Panagiotis Kanavos
This should be the responsibility of the one initializing the class to ensure that the properties are non-nullkelas harus selalu dalam keadaan valid. Jika nulltidak diizinkan, properti tidak boleh nol. Mungkin, alih-alih string dasar Anda harus menggunakan kelas khusus untuk URL yang dapat memiliki nilai atau None`Hilang`, seperti kelas Opsi di F #. C # 8 memungkinkan Anda untuk menulis kelas seperti itu dan memeriksanya dengan pencocokan pola
Panagiotis Kanavos
@ Panagiotis Kanavos, Kelas, dalam kasus saya, memiliki kendala untuk menjadi konstruktor tanpa parameter. Jadi saya harus menggunakan Properti Initializer: public string ServiceUrl { get; set; } = default! ;. Saya berharap Roslyn mungkin di masa depan memiliki cara untuk menangani inisialisasi Terlambat di luar ruang lingkup aktor. Saya menggunakan MayBe <T> (seperti kelas Opsi), tetapi saya beralih ke Jenis Referensi yang dapat dibatalkan dalam c # 8 untuk kode baru.
M.Hassan
NRT bukan Maybes, pada kenyataannya, Maybes sekarang bahkan lebih penting dan lebih mudah digunakan. Asalkan tentu saja mereka dibuat menggunakan idiom C # yang membuatnya mudah digunakan dengan pencocokan pola
Panagiotis Kanavos

Jawaban:

9

Solusi berikutnya direkomendasikan oleh EF Core & EF6, lihat

1) Dengan menginisialisasi null!dengan operator yang pemaaf

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

2) Menggunakan bidang dukungan:

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

M.Hassan
sumber
Pertanyaannya menyebutkan bahwa dia tidak dapat menggunakan !operator.
Athanasios Kataras
Saya tidak bisa menggunakan! dengan tipe, tetapi tautan yang saya sebutkan menunjukkan bagaimana menginisialisasi menggunakan null !. Ini solusi penyelesaian masalah. Saya memodifikasi pertanyaan.
M.Hassan
8

Jika tidak dapat dibatalkan, lalu apa yang dapat dilakukan kompiler ketika objek diinisialisasi?

Nilai default dari string adalah nol, jadi Anda akan melakukannya

  1. baik perlu menetapkan nilai default string dalam deklarasi

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

  2. Atau inisialisasi nilai dalam konstruktor default sehingga Anda akan menghilangkan peringatan

  3. Gunakan !operator (yang tidak bisa Anda gunakan)

  4. Buat itu nullable seperti yang disebutkan robbpriestley.

Athanasios Kataras
sumber
4
Atau menambahkan konstruktor yang menerima URL layanan sebagai string yang tidak dapat dibatalkan, tentu saja.
Jon Skeet
ServiceUrl'tidak boleh = String.Empty. Ada properti lain dari tipe kompleks yang tidak bisa nol, jadi saya gunakan defaultseperti: 'public MyClass MyProperty {get; set; } = default! 'Untuk menghentikan peringatan. Kelas ini (dan lainnya) adalah konstruktor tanpa parameter dan akhir-akhir ini diinisialisasi di luar ruang lingkup ctor.
M.Hassan
0

Hal lain yang mungkin berguna dalam beberapa skenario:

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

Dapat digunakan di atas anggota atau tipe keseluruhan.


Namun hal lain yang perlu dipertimbangkan adalah menambahkan #nullable disabledi atas file untuk menonaktifkan referensi nullable untuk seluruh file.

Shimmy Weitzhandler
sumber