Kiểu tham chiếu không thể xóa trong C # 8 khi sử dụng các lớp DTO với ORM


9

Tôi đã kích hoạt tính năng này trong một dự án có các lớp đối tượng truyền dữ liệu (DTO), như được đưa ra dưới đây:

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

Nhưng tôi nhận được lỗi:

CS8618: Thuộc tính không thể rỗng 'ServiceUrl' chưa được khởi tạo. Xem xét khai báo tài sản là nullable.

Đây là lớp DTO, vì vậy tôi không khởi tạo các thuộc tính. Đây sẽ là trách nhiệm của mã khởi tạo lớp để đảm bảo rằng các thuộc tính là không rỗng.

Ví dụ, người gọi có thể làm:

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

Câu hỏi của tôi: Làm thế nào để xử lý các lỗi như vậy trong các lớp DTO khi bối cảnh vô hiệu hóa của C # 8 được bật?


3
Khi bạn thực hiện khởi tạo xây dựng theo cách bạn hiển thị, hàm tạo mặc định sẽ chạy (khởi tạo ServiceUrl thành giá trị mặc định của nó (mà, đối với chuỗi, là null)). Sau đó, câu lệnh khởi tạo chạy. Nếu bạn muốn nó không có giá trị, nó cần thoát khỏi tất cả các hàm tạo được khởi tạo
Flydog57

POCO không có nghĩa là nó không có hàm tạo hoặc các thuộc tính không được khởi tạo. Nó có nghĩa là Plain Old C# Object. Chỉ là một đối tượng như bất kỳ đối tượng nào khác, mà không kế thừa từ bất kỳ lớp đặc biệt nào. Tôi nghi ngờ bạn có một câu hỏi khác nhau . Cách tạo DTO -Data Transfer Objects
Panagiotis Kanavos

This should be the responsibility of the one initializing the class to ensure that the properties are non-nullcác lớp nên ở trạng thái hợp lệ luôn. Nếu nullkhông được phép, tài sản sẽ không bao giờ có giá trị. Có lẽ, thay vì một chuỗi cơ bản, bạn nên sử dụng một lớp chuyên biệt cho URL có thể có giá trị Noneor` Missing`, như lớp Tùy chọn trong F #. C # 8 cho phép bạn viết các lớp như vậy và kiểm tra chúng với khớp mẫu
Panagiotis Kanavos

@Panagiotis Kanavos, Lớp, trong trường hợp của tôi, có một ràng buộc là Trình xây dựng không tham số. Vì vậy, tôi phải sử dụng Trình khởi tạo thuộc tính : public string ServiceUrl { get; set; } = default! ;. Tôi hy vọng Roslyn có thể có một cách để xử lý việc khởi tạo muộn ngoài phạm vi của ctor. Tôi đã sử dụng MayBe <T> (như lớp Tùy chọn), nhưng tôi đã chuyển sang Loại tham chiếu không thể thực hiện được trong c # 8 cho mã mới.
M.Hassan

NRTs không Maybes, trên thực tế, Maybes hiện nay thậm chí nhiều hơn nữa quan trọng và dễ dàng hơn để sử dụng. Tất nhiên với điều kiện là họ xây dựng bằng các thành ngữ C # giúp họ dễ dàng làm việc với khớp mẫu
Panagiotis Kanavos

Câu trả lời:


9

Giải pháp tiếp theo được khuyến nghị bởi EF Core & EF6, xem

1) Bằng cách khởi tạo null!với toán tử tha thứ

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

2) Sử dụng trường sao lưu:

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


Câu hỏi đề cập rằng anh ta không thể sử dụng !toán tử.
Athanasios Kataras

Tôi không thể sử dụng! với loại, nhưng liên kết tôi đã đề cập cho thấy cách khởi tạo bằng null!. Đó là một giải pháp khắc phục. Tôi đã sửa đổi câu hỏi.
M.Hassan

8

Nếu nó không null, thì trình biên dịch có thể làm gì khi đối tượng được khởi tạo?

Giá trị mặc định của chuỗi là null, vì vậy bạn sẽ

  1. hoặc cần gán một giá trị mặc định chuỗi trong khai báo

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

  2. Hoặc khởi tạo giá trị trong hàm tạo mặc định để bạn thoát khỏi cảnh báo

  3. Sử dụng !toán tử (mà bạn không thể sử dụng)

  4. Làm cho nó vô giá trị như robbpriestley đã đề cập.


4
Hoặc thêm một hàm tạo chấp nhận URL dịch vụ dưới dạng một chuỗi không thể rỗng, tất nhiên.
Jon Skeet

ServiceUrl'không thể = String.Empty. Có các Thuộc tính khác thuộc loại phức tạp không thể rỗng, vì vậy tôi đã sử dụng defaultnhư: 'công khai MyClass MyProperty {get; bộ; } = mặc định! 'để dừng cảnh báo. Lớp này (và các lớp khác) là hàm tạo không tham số và gần đây được khởi tạo bên ngoài phạm vi của ctor.
M.Hassan

0

Một điều khác có thể có ích trong một số tình huống:

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

Có thể được sử dụng trên đầu trang của thành viên hoặc toàn bộ loại.


Tuy nhiên, một điều khác cần xem xét là thêm #nullable disablevào đầu tệp để vô hiệu hóa tham chiếu nullable cho toàn bộ tệp.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.