ทำไมสิ่งนี้ถึงไม่คอมไพล์
int? number = true ? 5 : null;
ไม่สามารถระบุประเภทของนิพจน์เงื่อนไขได้เนื่องจากไม่มีการแปลงโดยนัยระหว่าง 'int' และ <null>
ทำไมสิ่งนี้ถึงไม่คอมไพล์
int? number = true ? 5 : null;
ไม่สามารถระบุประเภทของนิพจน์เงื่อนไขได้เนื่องจากไม่มีการแปลงโดยนัยระหว่าง 'int' และ <null>
คำตอบ:
ข้อมูลจำเพาะ (§7.14) กล่าวว่าสำหรับการแสดงออกเงื่อนไขb ? x : y
มีสามความเป็นไปได้อย่างใดอย่างหนึ่งx
และy
ทั้งสองมีประเภทและบางเงื่อนไขที่ดีจะพบเพียงคนเดียวx
และy
มีประเภทและบางเงื่อนไขที่ดีจะได้พบหรือข้อผิดพลาดเวลารวบรวม เกิดขึ้น ที่นี่ "เงื่อนไขที่ดีบางอย่าง" หมายถึงการแปลงบางอย่างที่เป็นไปได้ซึ่งเราจะได้รับรายละเอียดด้านล่าง
ทีนี้ลองหันไปหาส่วนที่เป็นส่วนประกอบของสเปค:
หากหนึ่งในนั้น
x
และy
มีประเภทและทั้งสองอย่างx
และy
แปลงได้โดยปริยายเป็นประเภทนั้นนั่นคือประเภทของการแสดงออกตามเงื่อนไข
ปัญหานี่คือสิ่งต่อไปนี้
int? number = true ? 5 : null;
ผลลัพธ์ที่มีเงื่อนไขหนึ่งรายการเท่านั้นที่มีประเภท นี่x
เป็นint
ตัวอักษรและy
เป็นnull
ที่ไม่ได้มีชนิดและnull
ไม่ได้แปลงสภาพไปยังปริยายint
1 ดังนั้นจึงไม่ตรงตาม "เงื่อนไขที่ดี" และเกิดข้อผิดพลาดในการคอมไพล์
มีอยู่สองวิธีรอบนี้:
int? number = true ? (int?)5 : null;
ที่นี่เรายังคงอยู่ในกรณีที่มีเพียงหนึ่งเดียวx
และy
มีประเภท โปรดทราบว่าnull
ยังไม่มีประเภทคอมไพเลอร์จะไม่มีปัญหาใด ๆ กับสิ่งนี้เพราะ(int?)5
และnull
ทั้งสองแปลงโดยปริยายเป็นint?
(§6.1.4และ§6.1.5)
วิธีอื่นชัดเจน:
int? number = true ? 5 : (int?)null;
แต่ตอนนี้เรามีการอ่านที่แตกต่างกันประโยคหนึ่งในสเปคที่จะเข้าใจว่าทำไมถึงไม่เป็นไร:
หาก
x
มีประเภทX
และy
มีประเภทY
แล้ว
หากการแปลงโดยนัย (§6.1) มีอยู่ตั้งแต่
X
ถึงถึงY
แต่ไม่ใช่จากY
ถึงX
ก็Y
จะเป็นประเภทของนิพจน์เงื่อนไขหากการแปลงโดยนัย (§6.1) มีอยู่ตั้งแต่
Y
ถึงถึงX
แต่ไม่ใช่จากX
ถึงY
ก็X
จะเป็นประเภทของนิพจน์เงื่อนไขมิฉะนั้นจะไม่สามารถระบุประเภทนิพจน์ได้และเกิดข้อผิดพลาดในการรวบรวม
นี่x
เป็นประเภทint
และเป็นประเภทy
int?
ไม่มีการแปลงโดยปริยายจากเป็นint?
ไปint
แต่จะมีการแปลงนัยจากint
ไปดังนั้นประเภทของการแสดงออกคือint?
int?
1 : โปรดทราบเพิ่มเติมว่าประเภทของด้านซ้ายมือจะถูกละเว้นในการกำหนดประเภทของนิพจน์เงื่อนไขซึ่งเป็นแหล่งที่มาของความสับสนทั่วไปที่นี่
new int?()
(int?)null
DateTime
เมื่อจำเป็นต้องมี infact(DateTime?)
null
ไม่มีประเภทที่สามารถระบุตัวตนได้ - เพียงแค่ต้องการการผลิตเพียงเล็กน้อยเพื่อให้มีความสุข:
int? number = true ? 5 : (int?)null;
int? number = true ? 5 : null as int?;
null
ไม่มีประเภทที่สามารถระบุตัวตนได้ ปัญหาก็คือว่าไม่มีการแปลงโดยปริยายจากไปnull
int
รายละเอียดที่นี่
int? number = true ? 5 : (int?)null;
และint? number = true ? (int?)5 : null;
ทั้งรวบรวม !! เกา, เกา
เป็นคนอื่นได้กล่าวถึง 5 เป็นint
และไม่สามารถแปลงไปโดยปริยายnull
int
นี่คือวิธีอื่นในการแก้ไขปัญหา:
int? num = true ? 5 : default(int?);
int? num = true ? 5 : new int?();
int? num = true ? 5 : null as int?;
int? num = true ? 5 : (int?)null;
int? num = true ? (int?)5 : null;
int? num = true ? 5 as int? : null;
int? num = true ? new int?(5) : null;
นอกจากนี้ทุกที่ที่คุณดูแล้วคุณยังสามารถใช้int?
Nullable<int>
ในบล็อกC# 9
นี้ได้รับอนุญาต
พิมพ์เป้าหมายหรือไม่? และ
บางครั้งมีเงื่อนไข ?? และ?: นิพจน์ไม่มีประเภทที่แชร์ที่ชัดเจนระหว่างสาขา กรณีดังกล่าวล้มเหลวในวันนี้ แต่ C # 9.0 จะอนุญาตหากมีประเภทเป้าหมายที่สาขาทั้งสองแปลงเป็น:
Person person = student ?? customer; // Shared base type
int? result = b ? 0 : null; // nullable value type
หรือตัวอย่างของคุณ:
// Allowed in C# 9.
int? number = true ? 5 : null;