เครื่องหมายคำถามและตัวดำเนินการ dot คืออะไร หมายถึงใน C # 6.0?


359

ด้วย C # 6.0 ในตัวอย่าง VS2015 เรามีโอเปอเรเตอร์ใหม่?.ซึ่งสามารถใช้ดังนี้:

public class A {
   string PropertyOfA { get; set; }
}

...

var a = new A();
var foo = "bar";
if(a?.PropertyOfA != foo) {
   //somecode
}

มันทำอะไรกันแน่?

คำตอบ:


499

มันเป็นโอเปอเรเตอร์ที่มีเงื่อนไข มันหมายถึงโดยทั่วไป:

"ประเมินตัวถูกดำเนินการแรกถ้าเป็นโมฆะให้หยุดด้วยผลลัพธ์เป็นโมฆะมิฉะนั้นประเมินตัวถูกดำเนินการตัวที่สอง (เป็นการเข้าถึงสมาชิกของตัวถูกดำเนินการแรก)"

ในตัวอย่างของคุณประเด็นคือถ้าaเป็นnullเช่นนั้นa?.PropertyOfAจะประเมินnullแทนที่จะโยนข้อยกเว้น - จากนั้นจะเปรียบเทียบnullการอ้างอิงนั้นกับfoo(โดยใช้การ==โอเวอร์โหลดของสตริง) พบว่าพวกเขาไม่เท่ากันและการดำเนินการจะเข้าสู่เนื้อหาของifคำสั่ง .

มันก็เป็นแบบนี้:

string bar = (a == null ? null : a.PropertyOfA);
if (bar != foo)
{
    ...
}

... ยกเว้นว่าaจะมีการประเมินเพียงครั้งเดียว

โปรดทราบว่าสิ่งนี้สามารถเปลี่ยนประเภทของการแสดงออกได้เช่นกัน FileInfo.Lengthตัวอย่างเช่นพิจารณา นั่นเป็นคุณสมบัติของประเภทlongแต่ถ้าคุณใช้กับตัวดำเนินการเงื่อนไขแบบ null คุณจะต้องจบลงด้วยนิพจน์ประเภทlong?:

FileInfo fi = ...; // fi could be null
long? length = fi?.Length; // If fi is null, length will be null

8
มันไม่ได้เรียกว่าตัวดำเนินการแบบมีเงื่อนไขว่างหรือไม่
SLAKs

1
@SLaks: ฉันคิดว่ามันเป็น "โมฆะตามเงื่อนไข" แต่ฉันอาจจะผิด ครั้งล่าสุดที่ฉันตรวจสอบเอกสารภาษาของ Roslyn มันไม่ได้ถูกเปลี่ยนชื่อเป็น บางทีแหล่งที่มาคือหน่วยงานที่นี่ - จะตรวจสอบ
Jon Skeet

3
@SLaks: แน่นอน ใน SyntaxKind เห็นได้ชัดว่า ConditionalAccess Expression ที่น่ารำคาญไม่ใช่ของพวกเขา ...
Jon Skeet

12
ฉันต้องการชื่อผู้ดำเนินการ "Elvis": P
Ahmed ilyas

3
สำหรับเร็กคอร์ดที่ฉันเห็นชื่อแตกต่างกันห้าชื่อสำหรับโอเปอเรเตอร์นี้: การนำทางอย่างปลอดภัยเงื่อนไขว่างเปล่าการแพร่กระจายว่าง
Gigi

81

มันจะมีประโยชน์มากเมื่อทำให้ลำดับชั้นและ / หรือวัตถุการทำแผนที่แบนราบ แทน:

if (Model.Model2 == null
  || Model.Model2.Model3 == null
  || Model.Model2.Model3.Model4 == null
  || Model.Model2.Model3.Model4.Name == null)
{
  mapped.Name = "N/A"
}
else
{
  mapped.Name = Model.Model2.Model3.Model4.Name;
}

มันสามารถเขียนได้เช่น (ตรรกะเดียวกันข้างต้น)

mapped.Name = Model.Model2?.Model3?.Model4?.Name ?? "N/A";

DotNetFiddle.Net ตัวอย่างการทำงาน

( โอเปอเรเตอร์การรวมศูนย์หรือโมฆะแตกต่างจากโอเปอเรเตอร์เงื่อนไขหรือโมฆะ )

นอกจากนี้ยังสามารถใช้งานด้านข้างของผู้ดำเนินการที่ได้รับมอบหมายกับการกระทำ แทน

Action<TValue> myAction = null;

if (myAction != null)
{
  myAction(TValue);
}

สามารถลดความซับซ้อนไปที่:

myAction?.Invoke(TValue);

ตัวอย่าง DotNetFiddle :

ใช้ระบบ

public class Program
{
  public static void Main()
  {
    Action<string> consoleWrite = null;

    consoleWrite?.Invoke("Test 1");

    consoleWrite = (s) => Console.WriteLine(s);

    consoleWrite?.Invoke("Test 2");
  }
}

ผลลัพธ์:

ทดสอบ 2


27
เพื่อช่วยให้ผู้คนมองหาสิ่งที่? is .. มันคือโอเปอเรเตอร์ null-coalescing และจะคืนค่าชื่อหากไม่ใช่ null มิฉะนั้นจะส่งคืน "N / A"
Steve

6
ฟิลิปส์ @Erik ฉันคิดว่าคุณต้องเพิ่ม || Model.Model2.Model3.Model4.Name == null จะมีตรรกะเดียวกันมิฉะนั้นในกรณีที่Model.Model2.Model3.Model4.Nameเป็นnull, mapped.Nameจะอยู่null
RazvanR

2
@ErikPhilips ไม่ได้อยู่ในหน้าเดียวกันฉันเดา โปรดลองดูสิ่งที่เกิดขึ้นในทั้งสองกรณีของคุณถ้าเป็นModel.Model2.Model3.Model4.Name null
RazvanR

1
ผลลัพธ์คือ "N / A" โปรดอ่านความคิดเห็นแรกอีกครั้ง DotNetFiddle.Net ตัวอย่างการทำงาน
Erik Philips

7
@ErikPhilips: นั่นไม่มีส่วนเกี่ยวข้องกับความคิดเห็นแรกเนื่องจากไม่เกี่ยวข้องกับตัวอย่างแรกของคุณ ในนี้คุณจะกระโดดลงไปในelse-branch และในขณะที่คุณตัวอย่างที่สองจะไปทดแทนmapped.Name = Model.Model2.Model3.Model4.Name -> mapped.Name = null mapped.Name = "N/A"ดูDotNetFiddle ที่แก้ไขแล้ว
derM

3

สิ่งนี้ค่อนข้างใหม่สำหรับ C # ซึ่งทำให้เราสามารถเรียกใช้ฟังก์ชันที่เกี่ยวข้องกับค่า Null หรือค่า Null ในวิธีการผูกมัด

วิธีเดิมในการบรรลุสิ่งเดียวกันคือ:

var functionCaller = this.member;
if (functionCaller!= null)
    functionCaller.someFunction(var someParam);

และตอนนี้มันทำให้ง่ายขึ้นด้วยเพียง:

member?.someFunction(var someParam);

ฉันขอแนะนำให้คุณอ่านที่นี่:

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-conditional-operators

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