วิธีการแปลง C # nullable int เป็น int


484

ฉันจะแปลงให้เป็นโมฆะintได้intอย่างไร สมมติว่าฉันมี 2 ประเภท int ดังนี้:

int? v1;  
int v2; 

ฉันต้องการที่จะกำหนดv1's v2มูลค่าให้กับ v2 = v1;จะทำให้เกิดข้อผิดพลาด ฉันจะแปลงv1เป็นv2อย่างไร


พฤติกรรมที่ต้องการเมื่อv1เป็นคือnullอะไร?
โซโลมอน Ucko

คำตอบ:


637

คำตอบอื่น ๆ ที่ถูกต้องทั้งหมด; ฉันแค่ต้องการเพิ่มอีกหนึ่งที่สะอาดกว่าเล็กน้อย:

v2 = v1 ?? default(int);

ใด ๆ ที่Nullable<T>สามารถแปลงได้โดยปริยายเพื่อTพิสูจน์ว่านิพจน์ทั้งหมดที่ถูกประเมินไม่สามารถส่งผลให้การกำหนดค่า null ให้กับ ValueType ดังนั้นตัวดำเนินการ null รวมกัน??เป็นเพียงไวยากรณ์น้ำตาลสำหรับผู้ประกอบการที่ประกอบไปด้วย:

v2 = v1 == null ? default(int) : v1;

... ซึ่งอยู่ในไวยากรณ์ของน้ำตาลสำหรับ if / else:

if(v1==null)
   v2 = default(int);
else
   v2 = v1;

นอกจากนี้ในฐานะของ. NET 4.0 Nullable<T>ยังมีวิธี "GetValueOrDefault ()" ซึ่งเป็นตัวรับสัญญาณที่ไม่ปลอดภัยซึ่งโดยทั่วไปแล้วจะทำการรวมกันเป็นโมฆะที่แสดงด้านบนดังนั้นสิ่งนี้ก็ใช้ได้เช่นกัน:

v2 = v1.GetValueOrDefault();

4
เป็นdefault(int)ความจำเป็นจริงๆ? มีอะไรผิดปกติกับง่ายๆ0?
โคลจอห์นสัน

4
มันจะใช้ได้กับตัวอย่างนี้ แต่ในกรณีทั่วไปแนะนำให้ใช้defaultตามความเหมาะสม เลขศูนย์ไม่ถูกต้องเสมอเป็นค่าเริ่มต้นน้อยกว่ามากดังนั้นหากคุณแทนที่intด้วยทั่วไปTคุณจะพบว่ารหัสของฉันทำงานในขณะที่ศูนย์ไม่ได้ ในบางเวอร์ชันของเฟรมเวิร์กในอนาคตdefaultอาจกลายเป็นโอเวอร์โหลดได้เช่นกัน หากและเมื่อสิ่งนั้นเกิดขึ้นรหัสที่ใช้ค่าเริ่มต้นจะสามารถใช้ประโยชน์ได้ง่ายในขณะที่ค่า Null ที่ชัดเจนหรือการกำหนดค่าศูนย์จะต้องเปลี่ยน
KeithS

5
สิ่งนี้ควรสูงขึ้นไปด้านบน:. NET 4.0, Nullable <T> มี "GetValueOrDefault ()"
RandomHandle

ขอบคุณที่กลับมาแก้ไขด้วย GetValueOrDefault!
CindyH

คุณอาจต้องระวัง DateTime เมื่อคุณใช้ค่าเริ่มต้น การดำเนินการนี้อาจแทรกวันที่เริ่มต้นแทนการว่างเปล่า
Ranch Camal


92

คุณสามารถใช้คุณสมบัติค่าสำหรับการมอบหมาย

v2 = v1.Value;

8
นอกจากนี้หากคุณไม่แน่ใจว่า v1 มีค่าเป็นโมฆะหรือไม่คุณสามารถใช้ตัวดำเนินการ null รวมเพื่อตั้งค่าทางเลือก เช่น v2 = v1 ?? 0;
Arjen

12
และให้แน่ใจว่าได้ตรวจสอบv1.HasValueก่อน
Yuck

3
MSDNกล่าวที่ว่านี้จะโยนยกเว้นถ้าเป็นv1 nullในความคิดของฉันนี่ไม่ใช่คำตอบที่ถูกต้อง
ventiseis

6
@ กิจกรรมฉันคิดว่าเป็นพฤติกรรมที่พึงประสงค์ - ฉันประหลาดใจมากที่คำตอบอื่น ๆ ก็โอเคกับการแปลงค่าศูนย์เป็น 0 หากคุณกำหนดประเภท nullable ให้เป็นประเภท non-nullable คุณควรแน่ใจว่า ค่านั้นไม่เป็นโมฆะจริง ๆ OP ไม่ได้พูดว่า "ฉันต้องการมอบหมาย v1 ถึง v2 หรือ 0 ถ้า v1 เป็นโมฆะ" แต่นั่นคือสิ่งที่ทุกคนคิด
Michael Mrozek


49

หากคุณรู้ว่าv1มีค่าคุณสามารถใช้Valueคุณสมบัติ:

v2 = v1.Value;

การใช้GetValueOrDefaultเมธอดจะกำหนดค่าหากมีอย่างใดอย่างหนึ่งไม่เช่นนั้นค่าเริ่มต้นสำหรับประเภทหรือค่าเริ่มต้นที่คุณระบุ:

v2 = v1.GetValueOrDefault(); // assigns zero if v1 has no value

v2 = v1.GetValueOrDefault(-1); // assigns -1 if v1 has no value

คุณสามารถใช้HasValueคุณสมบัติเพื่อตรวจสอบว่าv1มีค่า:

if (v1.HasValue) {
  v2 = v1.Value;
}

นอกจากนี้ยังมีการสนับสนุนภาษาสำหรับGetValueOrDefault(T)วิธีการ:

v2 = v1 ?? -1;

คุณไม่ควรใช้ค่าโดยไม่ตรวจสอบก่อนเพื่อดูว่ามีค่าหรือไม่ ใช้ ?? ผู้ประกอบการแทน
ปีเตอร์


28

GetValueOrDefault()

ดึงค่าของวัตถุ ถ้ามันเป็นโมฆะมันจะส่งกลับค่าเริ่มต้นของ int ซึ่งก็คือ 0

ตัวอย่าง:

v2= v1.GetValueOrDefault();


21

หากค่าเริ่มต้นสำหรับประเภทที่กำหนดเป็นผลลัพธ์ที่ยอมรับได้:

if (v1.HasValue)
    v2 = v1.GetValueOrDefault();

หากคุณต้องการค่าเริ่มต้นที่แตกต่างกันเมื่อไม่ได้กำหนดผลลัพธ์:

v2 = v1.GetValueOrDefault(255);    // or any valid value for int in place of 255

หากคุณต้องการคืนค่า (ไม่ว่าเมธอดจะล้มเหลวหรือไม่ก็ตาม):

v2 = v1.GetValueOrDefault();


.NET 4.7.2: GetValueOrDefault()ส่งคืนค่าฟิลด์โดยไม่ตรวจสอบใด ๆ


15

เท่าที่ฉันกังวลทางออกที่ดีที่สุดคือการใช้GetValueOrDefault()วิธีการ

v2 = v1.GetValueOrDefault();

อันนี้มีประโยชน์ที่สุดสำหรับฉัน
Liakat

11

การแปลง Int เป็นค่าที่ไม่สามารถแปลงได้นั้นสามารถทำได้ดังนี้:

v2=(int)v1;

9
ถ้า v1 เป็นโมฆะสิ่งนี้จะทำให้เกิด InvalidOperationException
MungeWrath

10

เป็นไปได้ด้วย v2 = Convert.ToInt32(v1);


สิ่งนี้จะใช้งานได้ทางเทคนิค แต่เทคนิคอื่น ๆ เช่น HasValue / Value หรือ GetValueOrDefault ทำงานได้อย่างมีประสิทธิภาพมากขึ้น
Brandon Barkley


9

การแปลงระหว่างที่เรียบง่ายv1และv2เป็นไปไม่ได้เพราะมีโดเมนที่มีขนาดใหญ่ของค่ากว่าv1 v2มันเป็นทุกอย่างที่v1สามารถถือรวมทั้งnullรัฐ ในการแปลงคุณต้องระบุอย่างชัดเจนว่าintจะใช้ค่าใดในการแมปnullสถานะ วิธีที่ง่ายที่สุดในการทำเช่นนี้คือ??ผู้ควบคุมเครื่อง

v2 = v1 ?? 0;  // maps null of v1 to 0

สิ่งนี้สามารถทำได้ในรูปแบบยาว

int v2;
if (v1.HasValue) {
  v2 = v1.Value;
} else {
  v2 = 0;
}

9

ขึ้นอยู่กับบริบทการใช้งานของคุณคุณอาจใช้คุณสมบัติการจับคู่รูปแบบของ C # 7:

int? v1 = 100;
if (v1 is int v2)
{
    Console.WriteLine($"I'm not nullable anymore: {v2}");
}

แก้ไข:

เนื่องจากบางคนกำลัง downvoting โดยไม่ต้องออกคำอธิบายฉันต้องการเพิ่มรายละเอียดบางอย่างเพื่ออธิบายเหตุผลในการรวมสิ่งนี้เป็นทางออกที่ทำงานได้

  • ตอนนี้การจับคู่รูปแบบของ C # 7ช่วยให้เราสามารถตรวจสอบประเภทของค่าและส่งค่าโดยปริยาย ในตัวอย่างด้านบน if-condition จะผ่านก็ต่อเมื่อค่าที่เก็บไว้ในv1นั้นเป็นชนิดที่เข้ากันได้กับประเภทสำหรับv2intซึ่งในกรณีนี้คือ มันดังต่อไปว่าเมื่อค่าสำหรับv1เป็นnullที่ถ้าสภาพจะล้มเหลวตั้งแต่ null intไม่สามารถมอบหมายให้ เพิ่มเติมอย่างถูกต้องไม่ได้เป็นnullint

  • ฉันต้องการเน้นว่าโซลูชันนี้อาจไม่ใช่ตัวเลือกที่ดีที่สุดเสมอไป ตามที่ฉันแนะนำฉันเชื่อว่าสิ่งนี้จะขึ้นอยู่กับบริบทการใช้งานที่แน่นอนของผู้พัฒนา หากคุณมีint?และต้องการดำเนินการตามเงื่อนไขกับมูลค่าของif-and-only-ifค่าที่กำหนดไม่เป็นโมฆะ (นี่เป็นครั้งเดียวเท่านั้นที่จะปลอดภัยการแปลง int ที่สามารถเปลี่ยนค่าได้เป็น int ปกติโดยไม่สูญเสียข้อมูล) การจับคู่รูปแบบอาจเป็นวิธีที่กระชับที่สุดวิธีหนึ่งในการทำเช่นนี้


ความจำเป็นในการแนะนำชื่อตัวแปรใหม่นั้นเป็นเรื่องที่โชคร้าย แต่นี่เป็นวิธีแก้ปัญหาที่ดีที่สุด (ปลอดภัยที่สุด) หากไม่มีค่าเริ่มต้นเนื่องจากไม่มีความเสี่ยงในการปรับHasValueเช็คของคุณโดยไม่ได้ตั้งใจ
Minexew

ฉันไม่เห็นความได้เปรียบใด ๆ กับวิธีการนี้มากกว่า v1.HasValue เป็นการตรวจสอบและจากนั้น v1.Value เพื่อเข้าถึงค่าพื้นฐาน ฉันจะไม่ลงคะแนน แต่ฉันคิดว่าปัญหานี้ได้รับการแก้ไขแล้วและเทคนิคใหม่ไม่ได้เพิ่มความชัดเจนให้กับปัญหา ฉันยังเปรียบเทียบว่ามันช้ากว่า 8-9%
Brandon Barkley

ขอบคุณสำหรับการเปรียบเทียบมันเป็นเรื่องดีที่รู้! ไม่ว่าคุณจะมองด้วยวิธีใดความแตกต่างก็จะดีที่สุด (เว้นแต่คุณจะทำสิ่งนี้ในบางช่วงเวลาที่สำคัญสำหรับฉัน) ฉันดูนี้เป็น "รัดกุม" หรืออาจเป็น "สำนวน" มากขึ้นเพราะอาศัยน้ำตาลไวยากรณ์อบเป็นภาษาแทน APIs มันเป็นอัตวิสัยเล็กน้อย แต่บางทีมันอาจเป็น "บำรุงรักษาได้มากกว่า" แม้ว่าจริง ๆ แล้วฉันชอบวิธีนี้มากกว่าพึ่งพาค่าเริ่มต้นตามคำแนะนำอื่น ๆ จำนวนมาก
Nicholas Miller

3

มันจะกำหนดค่าของv1ถึงv2หากไม่เป็นโมฆะมิฉะนั้นจะใช้ค่าเริ่มต้นเป็นศูนย์

v2=v1??0

หรือด้านล่างเป็นวิธีอื่นในการเขียน

v2 = v1.HasValue?v1:0


-1
 int v2= Int32.Parse(v1.ToString());

5
ในขณะที่รหัสนี้อาจตอบคำถาม แต่มีบริบทเพิ่มเติมเกี่ยวกับสาเหตุและ / หรือวิธีการที่รหัสนี้ตอบคำถามช่วยปรับปรุงมูลค่าระยะยาว
xiawi

1
มันเป็นการดีกว่าที่จะใช้วิธี "ปฏิบัติที่ดีที่สุด" เพื่อแกะตัวเลือกแทนที่จะใช้เล่ห์เหลี่ยมเล่ห์เหลี่ยม ดูdocs.microsoft.com/en-us/dotnet/csharp/language-reference/…สำหรับการอ้างอิง
lorg

เมื่อตอบคำถามอายุแปดปีพร้อมคำตอบที่มีอยู่สิบห้าข้อสิ่งสำคัญคือต้องอธิบายว่าคำถามของคุณคืออะไรในมุมมองใหม่และให้สังเกตว่าเวลาผ่านไปเปลี่ยนคำตอบแล้ว คำตอบรหัสเท่านั้นที่สามารถปรับปรุงได้ตลอดเวลาโดยการเพิ่มคำอธิบายบางอย่าง
Jason Aller
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.