ประเภทการอ้างอิงเป็นโมฆะใน C # 8 เมื่อใช้คลาส DTO กับ ORM


9

ฉันเปิดใช้งานคุณลักษณะนี้ในโครงการที่มีคลาส data data object (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มันหมายความว่า เพียงแค่วัตถุเหมือนกันโดยไม่สืบทอดจากคลาสพิเศษใด ๆ ฉันสงสัยว่าคุณมีความแตกต่างกันคำถาม วิธีสร้าง DTOs -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'ขาดหายไป' เช่นคลาสตัวเลือกใน F # C # 8 ช่วยให้คุณสามารถเขียนคลาสดังกล่าวและตรวจสอบด้วยการจับคู่รูปแบบ
Panagiotis Kanavos

@Panagiotis Kanavos, คลาส, ในกรณีของฉัน, มีข้อ จำกัด ในการเป็น Constructor ที่ไม่มีพารามิเตอร์ ดังนั้นผมจึงต้องใช้ Initializer public string ServiceUrl { get; set; } = default! ;อสังหาริมทรัพย์: ฉันหวังว่า Roslyn อาจมีวิธีจัดการกับการกำหนดค่าเริ่มต้นล่าช้านอกขอบเขตของ ctor ฉันใช้ MayBe <T> (เหมือนคลาส Option) แต่ฉันเปลี่ยนเป็นประเภทอ้างอิงที่ไม่มีค่าใน c # 8 สำหรับรหัสใหม่
M.Hassan

NRTs ไม่ได้ตัวสำรองในความเป็นจริงตัวสำรองอยู่ในขณะนี้แม้จะมากขึ้นที่สำคัญและง่ายต่อการใช้งาน ให้แน่นอนว่าพวกเขากำลังสร้างโดยใช้สำนวน 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));
        }


คำถามที่กล่าวถึงว่าเขาไม่สามารถใช้!โอเปอเรเตอร์ได้
Athanasios Kataras

ฉันไม่สามารถใช้! ด้วยประเภท แต่ลิงค์ที่ฉันกล่าวถึงแสดงวิธีเริ่มต้นด้วย null! มันเป็นวิธีแก้ปัญหา ฉันแก้ไขคำถาม
M.Hassan

8

ถ้ามันไม่เป็นโมฆะคอมไพเลอร์สามารถทำอะไรได้เมื่อวัตถุนั้นถูกเตรียมใช้งาน?

ค่าเริ่มต้นของสตริงเป็นโมฆะดังนั้นคุณจะ

  1. อาจจำเป็นต้องกำหนดค่าเริ่มต้นของสตริงในการประกาศ

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

  2. หรือเริ่มต้นค่าในตัวสร้างเริ่มต้นเพื่อที่คุณจะได้กำจัดคำเตือน

  3. ใช้!โอเปอเรเตอร์ (ที่คุณไม่สามารถใช้งานได้)

  4. ทำให้เป็นโมฆะตามที่ robbpriestley พูดถึง


4
หรือเพิ่มคอนสตรัคเตอร์ที่ยอมรับ URL บริการเป็นสตริงที่ไม่สามารถยกเลิกได้
Jon Skeet

ServiceUrl'ไม่สามารถ = String.Empty มีคุณสมบัติอื่น ๆ ของประเภทที่ซับซ้อนที่ไม่สามารถเป็นโมฆะดังนั้นฉันใช้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.