ไม่สามารถระบุประเภทของนิพจน์เงื่อนไขได้เนื่องจากไม่มีการแปลงโดยนัยระหว่าง 'int' และ <null>


167

ทำไมสิ่งนี้ถึงไม่คอมไพล์

int? number = true ? 5 : null;

ไม่สามารถระบุประเภทของนิพจน์เงื่อนไขได้เนื่องจากไม่มีการแปลงโดยนัยระหว่าง 'int' และ <null>


คำอธิบายที่ดีที่สุดและเป็นตัวอย่าง ... http://stackoverflow.com/questions/858080/nullable-types-and-the-ternary-operator-why-is-10-null-forbidden?answertab=active#tab -TOP
Parth Savadiya

คำตอบ:


341

ข้อมูลจำเพาะ (§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 : โปรดทราบเพิ่มเติมว่าประเภทของด้านซ้ายมือจะถูกละเว้นในการกำหนดประเภทของนิพจน์เงื่อนไขซึ่งเป็นแหล่งที่มาของความสับสนทั่วไปที่นี่


4
การอ้างอิงที่ดีเพื่อแสดงให้เห็นว่าทำไมสิ่งนี้ถึงเกิดขึ้น - +1!
JerKimball

8
เป็นอีกตัวเลือกหนึ่งในสถานที่ของnew int?() (int?)null
Guvante

1
นี่ก็เป็นกรณีเช่นกันถ้าคุณมีประเภทเขตข้อมูลที่เป็นโมฆะตัวอย่างเช่น DateTime ที่ไม่สามารถใช้ได้และคุณลองและส่งข้อมูลไปDateTimeเมื่อจำเป็นต้องมี infact(DateTime?)
Mike Upjohn

73

null ไม่มีประเภทที่สามารถระบุตัวตนได้ - เพียงแค่ต้องการการผลิตเพียงเล็กน้อยเพื่อให้มีความสุข:

int? number = true ? 5 : (int?)null;

3
หรือคุณสามารถทำได้int? number = true ? 5 : null as int?;
แบรดเอ็ม

คำตอบที่ดีที่จับประเด็น การอ่านที่เกี่ยวข้องดี: ericlippert.com/2013/05/30/what-the-meaning-of-is-is
Benjamin Gruenbaum

ปัญหาไม่ใช่ว่าnullไม่มีประเภทที่สามารถระบุตัวตนได้ ปัญหาก็คือว่าไม่มีการแปลงโดยปริยายจากไปnull intรายละเอียดที่นี่
สัน

สิ่งที่น่าสนใจก็คือว่าint? number = true ? 5 : (int?)null;และint? number = true ? (int?)5 : null;ทั้งรวบรวม !! เกา, เกา
davidhq

2
ฉันครอบคลุมว่าทำไมนี้เกิดขึ้นในของฉันคำตอบ
สัน

4

เป็นคนอื่นได้กล่าวถึง 5 เป็นintและไม่สามารถแปลงไปโดยปริยายnullint

นี่คือวิธีอื่นในการแก้ไขปัญหา:

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>


1

ในบล็อก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;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.