วิ่งข้ามรหัสบรรทัดนี้:
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
เครื่องหมายคำถามสองข้อหมายความว่าอย่างไร การค้นหาใน Google เป็นเรื่องยาก
วิ่งข้ามรหัสบรรทัดนี้:
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
เครื่องหมายคำถามสองข้อหมายความว่าอย่างไร การค้นหาใน Google เป็นเรื่องยาก
คำตอบ:
มันเป็นตัวดำเนินการรวมศูนย์ว่างและค่อนข้างเหมือนกับผู้ประกอบการที่สาม (ทันทีถ้า) ดูยัง?? ผู้ประกอบการ - MSDN
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
ขยายเป็น:
FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();
ซึ่งเพิ่มเติมขยายไปที่:
if(formsAuth != null)
FormsAuth = formsAuth;
else
FormsAuth = new FormsAuthenticationWrapper();
ในภาษาอังกฤษหมายถึง "ถ้าสิ่งใดที่อยู่ทางซ้ายไม่เป็นโมฆะให้ใช้สิ่งนั้นมิฉะนั้นใช้สิ่งที่อยู่ทางขวา"
โปรดทราบว่าคุณสามารถใช้หมายเลขเหล่านี้ตามลำดับ ข้อความต่อไปนี้จะกำหนดคนแรกที่ไม่ใช่ null Answer#
ไปAnswer
(ถ้าคำตอบทั้งหมดเป็นโมฆะแล้วAnswer
เป็นโมฆะ):
string Answer = Answer1 ?? Answer2 ?? Answer3 ?? Answer4;
นอกจากนี้ยังมีมูลค่าการกล่าวขวัญในขณะที่การขยายด้านบนเทียบเท่ากับแนวคิดผลลัพธ์ของแต่ละนิพจน์จะถูกประเมินเพียงครั้งเดียว นี่เป็นสิ่งสำคัญหากตัวอย่างเช่นนิพจน์คือการเรียกใช้เมธอดที่มีผลข้างเคียง (ให้เครดิตกับ @Joey เพื่อชี้เรื่องนี้)
??
คือการเชื่อมโยงทางด้านซ้ายเพื่อให้เทียบเท่ากับa ?? b ?? c ?? d
((a ?? b) ?? c ) ?? d
"ตัวดำเนินการที่ได้รับมอบหมายและตัวดำเนินการที่ประกอบไปด้วย (? :) เป็นตัวเชื่อมโยงที่ถูกต้องตัวดำเนินการไบนารีอื่น ๆ ทั้งหมดจะอยู่ทางด้านซ้าย" ที่มา: msdn.microsoft.com/en-us/library/ms173145.aspx
เพียงเพราะไม่มีใครพูดคำวิเศษ: ยังเป็นผู้ประกอบการโมฆะการรวมตัวกัน มันกำหนดไว้ในส่วน 7.12 ของC # 3.0 สเปคภาษา
มันมีประโยชน์มากโดยเฉพาะอย่างยิ่งเพราะวิธีการทำงานเมื่อใช้หลายครั้งในการแสดงออก การแสดงออกของแบบฟอร์ม:
a ?? b ?? c ?? d
จะให้ผลของการแสดงออกa
ถ้ามันไม่ใช่ null มิฉะนั้นลองb
มิฉะนั้นลองมิฉะนั้นลองc
d
มันลัดวงจรทุกจุด
นอกจากนี้หากประเภทของd
ไม่สามารถยกเลิกได้ประเภทของการแสดงออกทั้งหมดจะไม่สามารถยกเลิกได้เช่นกัน
มันเป็นตัวดำเนินการรวมศูนย์ว่าง
http://msdn.microsoft.com/en-us/library/ms173224.aspx
ใช่เกือบจะเป็นไปไม่ได้ที่จะค้นหาเว้นแต่คุณจะรู้ว่ามันคืออะไร :-)
แก้ไข: และนี่คือคุณสมบัติที่ยอดเยี่ยมจากคำถามอื่น คุณสามารถโยงพวกเขา
ขอบคุณทุกคนนี่คือคำอธิบายที่กระชับที่สุดที่ฉันพบในเว็บไซต์ MSDN:
// y = x, unless x is null, in which case y = -1.
int y = x ?? -1;
-1
เป็นเพียงธรรมดาint
ซึ่งเป็นที่ไม่ใช่ nullable)
x
เป็นประเภทint?
แต่y
เป็นประเภทint
คุณสามารถเขียนint y = (int)(x ?? -1)
ได้ มันจะแยกx
ไปยังint
ถ้ามันไม่ได้null
หรือกำหนด-1
ไปy
ถ้ามีx
null
??
มีไว้เพื่อให้ค่าสำหรับประเภท nullable เมื่อค่าเป็นโมฆะ ดังนั้นถ้า FormsAuth เป็นโมฆะมันจะส่งคืน FormsAuthenticationWrapper ใหม่ ()
เครื่องหมายคำถามสองข้อ (??) ระบุว่าเป็นตัวดำเนินการรวมกัน
การรวมตัวดำเนินการส่งคืนค่า NON-NULL แรกจากเชน คุณสามารถดูวิดีโอ youtube นี้ซึ่งแสดงให้เห็นถึงสิ่งทั้งหมดในทางปฏิบัติ
แต่ให้ฉันเพิ่มสิ่งที่วิดีโอพูดเพิ่ม
หากคุณเห็นความหมายภาษาอังกฤษของการรวมตัวกันมันบอกว่า "รวมเข้าด้วยกัน" ตัวอย่างด้านล่างเป็นรหัสการรวมตัวง่ายซึ่งเชื่อมโยงสี่สาย
ดังนั้นถ้าstr1
เป็นnull
ก็จะพยายามstr2
ถ้าstr2
เป็นnull
ก็จะพยายามstr3
ไปเรื่อย ๆ จนกว่าจะพบสตริงที่มีค่าที่ไม่ใช่โมฆะ
string final = str1 ?? str2 ?? str3 ?? str4;
กล่าวอย่างง่าย ๆ ว่าโอเปอเรเตอร์ Coalescing ส่งคืนค่า NON-NULL แรกจาก chain
มันเป็นมือสั้น ๆ สำหรับผู้ประกอบการที่สาม
FormsAuth = (formsAuth != null) ? formsAuth : new FormsAuthenticationWrapper();
หรือสำหรับผู้ที่ไม่ได้ประกอบไปด้วย:
if (formsAuth != null)
{
FormsAuth = formsAuth;
}
else
{
FormsAuth = new FormsAuthenticationWrapper();
}
!= null
) และแบบที่สองformsAuth
(หลัง?
) อาจเปลี่ยนแปลงได้ ในรูปแบบว่างรวมกันทั้งสองใช้ค่าที่คุณได้ระบุไว้โดยปริยาย
หากคุณคุ้นเคยกับทับทิมมันก็||=
เหมือนกับ C # ??
กับฉัน นี่คือทับทิมบางส่วน:
irb(main):001:0> str1 = nil
=> nil
irb(main):002:0> str1 ||= "new value"
=> "new value"
irb(main):003:0> str2 = "old value"
=> "old value"
irb(main):004:0> str2 ||= "another new value"
=> "old value"
irb(main):005:0> str1
=> "new value"
irb(main):006:0> str2
=> "old value"
และใน C #:
string str1 = null;
str1 = str1 ?? "new value";
string str2 = "old value";
str2 = str2 ?? "another new value";
x ||= y
desugars กับสิ่งที่ชอบx = x || y
ดังนั้น??
จริง ๆ แล้วคล้ายกับธรรมดา||
ในทับทิม
??
เพียงใส่ใจเกี่ยวกับnull
ในขณะที่||
ผู้ประกอบการในรูบีในขณะที่ภาษาส่วนใหญ่เป็นเรื่องเกี่ยวกับnull
, false
หรืออะไรที่สามารถได้รับการพิจารณาบูลด้วยค่าตัวfalse
(เช่นในบางภาษา""
) นี่ไม่ใช่สิ่งที่ดีหรือไม่ดีมีเพียงความแตกต่าง
รวมตัวดำเนินการ
มันเทียบเท่ากับ
FormsAuth = formsAUth == null ? new FormsAuthenticationWrapper() : formsAuth
ไม่มีอะไรอันตรายเกี่ยวกับเรื่องนี้ ที่จริงแล้วมันสวยงาม คุณสามารถเพิ่มค่าเริ่มต้นได้หากต้องการตัวอย่างเช่น:
รหัส
int x = x1 ?? x2 ?? x3 ?? x4 ?? 0;
int? x1 = null;
ใช่แล้ว
x1
- x4
ต้องเป็นประเภท nullable: มันไม่มีเหตุผลที่จะพูดได้อย่างมีประสิทธิภาพ "ผลลัพธ์คือ0
ถ้าx4
เป็นค่าที่ไม่สามารถใช้" ( null
) "ประเภทที่ว่างเปล่า" ที่นี่มีทั้งประเภทค่าที่เป็นโมฆะและประเภทการอ้างอิงแน่นอน เป็นข้อผิดพลาดในการคอมไพล์หากตัวแปรหนึ่งตัวหรือมากกว่าถูกล่ามโซ่ (ยกเว้นอันสุดท้าย) ไม่เป็นโมฆะ
ชี้เป็นอย่างถูกต้องในคำตอบมากมายที่เป็น "ผู้ประกอบ null หลอมรวม" ( ?? ) พูดซึ่งคุณอาจต้องการตรวจสอบญาติของตน "ผู้ประกอบการ Null เงื่อนไข" ( ?.หรือ? [ ) ที่เป็นผู้ประกอบการที่ หลายครั้งมันถูกใช้ร่วมกับ??
ใช้เพื่อทดสอบหาค่าว่างก่อนดำเนินการการเข้าถึงสมาชิก ( ?. ) หรือดัชนี ( ? [ ) ตัวดำเนินการเหล่านี้ช่วยให้คุณเขียนรหัสน้อยลงเพื่อจัดการกับการตรวจสอบค่าว่าง
ตัวอย่างเช่น:
// if 'customers' or 'Order' property or 'Price' property is null,
// dollarAmount will be 0
// otherwise dollarAmount will be equal to 'customers.Order.Price'
int dollarAmount = customers?.Order?.Price ?? 0;
วิธีเก่าๆ และ?? ในการทำเช่นนี้คือ
int dollarAmount = customers != null
&& customers.Order!=null
&& customers.Order.Price!=null
? customers.Order.Price : 0;
ซึ่งเป็น verbose และยุ่งยากมากขึ้น
เพื่อความสนุกของคุณเท่านั้น (รู้ว่าคุณคือพวก C # ทั้งหมด ;-)
ฉันคิดว่ามันมีต้นกำเนิดใน Smalltalk ซึ่งมันมีมาหลายปีแล้ว มันถูกกำหนดไว้ที่นั่นเป็น:
ในวัตถุ:
? anArgument
^ self
ใน UndefinedObject (คลาส aka ของศูนย์):
? anArgument
^ anArgument
มีทั้งการประเมิน (?) และเวอร์ชั่นที่ไม่ผ่านการประเมิน (??)
มันมักจะพบในวิธีการทะเยอทะยานสำหรับตัวแปรเอกชน (ตัวอย่าง) เริ่มต้นขี้เกียจซึ่งถูกปล่อยให้เป็นศูนย์จนจำเป็นจริงๆ
ตัวอย่างบางส่วนของการรับค่าโดยใช้การรวมกันที่นี่ไม่มีประสิทธิภาพ
สิ่งที่คุณต้องการคือ:
return _formsAuthWrapper = _formsAuthWrapper ?? new FormsAuthenticationWrapper();
หรือ
return _formsAuthWrapper ?? (_formsAuthWrapper = new FormsAuthenticationWrapper());
สิ่งนี้ป้องกันไม่ให้วัตถุถูกสร้างขึ้นใหม่ทุกครั้ง แทนที่จะเป็นโมฆะตัวแปรส่วนตัวที่เหลือเป็นโมฆะและวัตถุใหม่ที่ถูกสร้างขึ้นในทุก ๆ การร้องขอสิ่งนี้ทำให้มั่นใจได้ว่าจะมีการกำหนดตัวแปรส่วนตัวถ้ามีการสร้างวัตถุใหม่
??
ประเมินทางลัดหรือไม่ new FormsAuthenticationWrapper();
มีการประเมินถ้าหากว่า _formsAuthWrapper
เป็นศูนย์
ฉันได้อ่านทั้งกระทู้นี้และอื่น ๆ อีกมากมาย แต่ฉันไม่สามารถหาคำตอบอย่างละเอียดได้เช่นนี้
โดยที่ฉันเข้าใจอย่างสมบูรณ์ว่า "ทำไมต้องใช้" และเมื่อใดจึงควรใช้ "และวิธีใช้"
รากฐานการสื่อสารของ Windows ถูกปลดปล่อยโดย Craig McMurtry ISBN 0-672-32948-4
มีสองสถานการณ์ทั่วไปที่หนึ่งต้องการทราบว่ามีการกำหนดค่าให้กับอินสแตนซ์ของประเภทค่าหรือไม่ สิ่งแรกคือเมื่ออินสแตนซ์แสดงถึงค่าในฐานข้อมูล ในกรณีเช่นนี้เราต้องการตรวจสอบอินสแตนซ์เพื่อตรวจสอบว่ามีค่าอยู่ในฐานข้อมูลหรือไม่ สถานการณ์อื่น ๆ ซึ่งเกี่ยวข้องกับเนื้อหาของหนังสือเล่มนี้มากกว่าคือเมื่ออินสแตนซ์แสดงรายการข้อมูลที่ได้รับจากแหล่งข้อมูลระยะไกลบางแห่ง อีกครั้งหนึ่งต้องการพิจารณาจากอินสแตนซ์ว่าได้รับค่าสำหรับรายการข้อมูลนั้นหรือไม่
.NET Framework 2.0 รวมคำจำกัดความชนิดทั่วไปที่ให้สำหรับกรณีเช่นนี้ซึ่งต้องการกำหนดค่า null ให้กับอินสแตนซ์ของประเภทค่าและทดสอบว่าค่าของอินสแตนซ์นั้นเป็นค่าว่างหรือไม่ นิยามประเภททั่วไปนั่นคือ System.Nullable ซึ่ง จำกัด อาร์กิวเมนต์ประเภททั่วไปที่อาจถูกแทนที่สำหรับ T เป็นประเภทค่า อินสแตนซ์ของชนิดที่สร้างจาก System.Nullable สามารถกำหนดค่าเป็น null ได้ แน่นอนค่าของพวกเขาเป็นโมฆะโดยค่าเริ่มต้น ดังนั้นประเภทที่สร้างขึ้นจาก System.Nullable อาจจะเรียกว่าเป็นประเภทค่า nullable System.Nullable มีคุณสมบัติ Value ซึ่งค่าที่กำหนดให้กับอินสแตนซ์ของประเภทที่สร้างจากมันสามารถรับได้หากค่าของอินสแตนซ์ไม่เป็นโมฆะ ดังนั้นหนึ่งสามารถเขียน:
System.Nullable<int> myNullableInteger = null;
myNullableInteger = 1;
if (myNullableInteger != null)
{
Console.WriteLine(myNullableInteger.Value);
}
ภาษาการเขียนโปรแกรม C # มีไวยากรณ์แบบย่อสำหรับการประกาศประเภทที่สร้างจาก System.Nullable ไวยากรณ์นั้นอนุญาตให้หนึ่งย่อ:
System.Nullable<int> myNullableInteger;
ถึง
int? myNullableInteger;
คอมไพเลอร์จะป้องกันไม่ให้หนึ่งพยายามกำหนดค่าของประเภทค่า nullable กับประเภทค่าสามัญด้วยวิธีนี้:
int? myNullableInteger = null;
int myInteger = myNullableInteger;
มันป้องกันหนึ่งจากการทำเช่นนั้นเพราะประเภทค่า nullable สามารถมีค่า null ซึ่งจริงจะมีในกรณีนี้และค่าที่ไม่สามารถกำหนดให้กับประเภทค่าสามัญ แม้ว่าคอมไพเลอร์จะอนุญาตรหัสนี้
int? myNullableInteger = null;
int myInteger = myNullableInteger.Value;
คำสั่งที่สองจะทำให้เกิดข้อยกเว้นจะถูกโยนเพราะความพยายามในการเข้าถึง System.Nullable.Value คุณสมบัติเป็นการดำเนินการที่ไม่ถูกต้องหากประเภทที่สร้างจาก System.Nullable ยังไม่ได้รับการกำหนดค่าที่ถูกต้องของ T ซึ่งไม่ได้เกิดขึ้นในนี้ กรณี.
วิธีหนึ่งที่เหมาะสมในการกำหนดค่าของชนิดค่า nullable ให้กับชนิดค่าปกติคือการใช้คุณสมบัติ System.Nullable.HasValue เพื่อตรวจสอบว่าค่าที่ถูกต้องของ T ถูกกำหนดให้กับชนิดค่า nullable หรือไม่:
int? myNullableInteger = null;
if (myNullableInteger.HasValue)
{
int myInteger = myNullableInteger.Value;
}
ตัวเลือกอื่นคือการใช้ไวยากรณ์นี้:
int? myNullableInteger = null;
int myInteger = myNullableInteger ?? -1;
โดยที่ myInteger จำนวนเต็มสามัญจะถูกกำหนดค่าของจำนวนเต็ม null "myNullableInteger" ถ้าหลังได้รับมอบหมายค่าจำนวนเต็มที่ถูกต้อง; มิฉะนั้น myInteger จะถูกกำหนดค่าเป็น -1
มันเป็นตัวดำเนินการรวมศูนย์ว่างที่ทำงานคล้ายกับตัวดำเนินการแบบไตรภาค
a ?? b => a !=null ? a : b
อีกจุดที่น่าสนใจสำหรับเรื่องนี้คือ "ประเภท nullable สามารถมีค่าหรืออาจจะไม่ได้กำหนด" ดังนั้นถ้าคุณพยายามที่จะกำหนดประเภทของค่าที่เป็นโมฆะให้เป็นประเภทของค่าที่ไม่เป็นโมฆะคุณจะได้รับข้อผิดพลาดในการรวบรวม
int? x = null; // x is nullable value type
int z = 0; // z is non-nullable value type
z = x; // compile error will be there.
ดังนั้นจะทำอย่างไรโดยใช้ ?? ผู้ประกอบการ:
z = x ?? 1; // with ?? operator there are no issues
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
เทียบเท่ากับ
FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();
แต่สิ่งที่ยอดเยี่ยมเกี่ยวกับเรื่องนี้ก็คือคุณสามารถโยงมันได้เหมือนกับที่คนอื่นพูด คนที่ไม่ได้สัมผัสก็คือคุณสามารถใช้มันเพื่อโยนข้อยกเว้น
A = A ?? B ?? throw new Exception("A and B are both NULL");
??
ผู้ประกอบการจะเรียกว่าผู้ประกอบการด้วย null coalescing มันจะส่งกลับตัวถูกดำเนินการทางซ้ายถ้าตัวถูกดำเนินการไม่เป็นโมฆะ มิฉะนั้นจะส่งคืนตัวถูกดำเนินการทางขวา
int? variable1 = null;
int variable2 = variable1 ?? 100;
ตั้งvariable2
ค่าเป็นvariable1
ถ้าvariable1
ไม่ใช่โมฆะ มิฉะนั้นถ้าvariable1 == null
ตั้งvariable2
เป็น 100
คนอื่นได้อธิบายNull Coalescing Operator
ค่อนข้างดี สำหรับผู้ที่สนใจมีไวยากรณ์สั้นลงที่นี้ (คำถาม SO):
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
เทียบเท่ากับสิ่งนี้:
FormsAuth ??= new FormsAuthenticationWrapper();
บางคนพบว่าอ่านง่ายและสั้นกระชับ