ความแตกต่างใน C # ระหว่างสไตล์ getter ที่แตกต่างกัน


154

บางครั้งฉันเห็นตัวย่อในคุณสมบัติของผู้ทะเยอทะยาน เช่นสองประเภทนั้น:

public int Number { get; } = 0

public int Number => 0;

ใครช่วยได้โปรดบอกฉันว่ามีความแตกต่างระหว่างทั้งสอง พวกเขาทำงานอย่างไร ทั้งคู่เป็นแบบอ่านอย่างเดียวหรือไม่

คำตอบ:


266

ใช่ทั้งคู่เป็นแบบอ่านอย่างเดียว แต่มีความแตกต่าง ในฟิลด์แรกจะมีเขตข้อมูลสำรองซึ่งเริ่มต้นเป็น 0 ก่อนที่ตัวสร้างจะดำเนินการ คุณสามารถเปลี่ยนค่าเฉพาะในตัวสร้างเช่นเดียวกับฟิลด์อ่านอย่างเดียวปกติ ผู้ทะเยอทะยานตัวเองเพียงส่งกลับค่าของสนาม

ในอันที่สอง getter จะส่งกลับค่า 0 ทุกครั้งโดยไม่มีฟิลด์ที่เกี่ยวข้อง

ดังนั้นเพื่อหลีกเลี่ยงการใช้คุณสมบัติที่ใช้งานอัตโนมัติหรือสมาชิกที่มีการแสดงออกเราจึงมี:

รุ่นแรก

private readonly int _number = 0;
public int Number { get { return _number; } }

รุ่นที่สอง

public int Number { get { return 0; } }

ตัวอย่างที่ชัดเจนของความแตกต่างอาจเห็นได้ดังนี้:

public DateTime CreationTime { get; } = DateTime.UtcNow;
public DateTime CurrentTime => DateTime.UtcNow;

หากคุณสร้างวัตถุเดียวCreationTimeคุณสมบัติของมันจะให้ผลลัพธ์เหมือนกันเสมอ - เนื่องจากมันถูกเก็บไว้ในเขตข้อมูลแบบอ่านอย่างเดียวซึ่งจะเริ่มต้นในการสร้างวัตถุ อย่างไรก็ตามทุกครั้งที่คุณเข้าถึงCurrentTimeคุณสมบัติที่จะทำให้DateTime.UtcNowมีการประเมินผลดังนั้นคุณจะได้รับผลลัพธ์ที่แตกต่างกัน


23
โปรดทราบว่ารุ่นที่สองจะไม่ส่งคืนค่าเดิมเสมอไป random.NextInt()หนึ่งตัวอย่างที่ดีคือถ้าคุณกลับ เวอร์ชันแรกจะประเมินว่าหนึ่งครั้งและจะมีค่าเท่ากันเสมอ ครั้งที่สองจะคืนค่าใหม่ทุกครั้ง

248

ข้อแตกต่างอย่างหนึ่งคือเมื่อ0ประเมินผล: เมื่อสร้างวัตถุหรือเมื่อใช้คุณสมบัติ

คุณสามารถเห็นสิ่งนี้ดีขึ้นด้วยคุณสมบัติ DateTime:

class SomeTestClass
{
    public DateTime Start { get; } = DateTime.Now;

    public DateTime Now => DateTime.Now;
}

Startคุณสมบัติช่วยให้กลับมาในเวลาเดียวกัน (เมื่ออินสแตนซ์ที่ถูกสร้างขึ้น) ในขณะที่Nowการเปลี่ยนแปลงเพื่อให้สอดคล้องกับเวลาปัจจุบัน

คำอธิบาย :

รุ่นแรก ("เริ่มต้น") ระบุค่าเริ่มต้นที่อาจถูกเขียนทับโดยตัวสร้าง นี่คือการประเมินเพียงครั้งเดียว
รุ่นที่สอง ("ตอนนี้") ให้การแสดงออกซึ่งจะเป็น "ทะเยอทะยาน" ของคุณสมบัตินี้ ดังนั้นนี่คือการประเมินทุกครั้งที่มีการอ่านคุณสมบัติ ไม่มีแม้แต่ฟิลด์สำรองที่ตัวสร้างสามารถเขียนทับได้


26
นี่คือความแตกต่างที่สำคัญที่สุดที่ฉันคิด
แมทธิว

14
คำตอบที่ได้รับการยอมรับอย่างแม่นยำที่สุดกำหนดความแตกต่างในรหัสตัวอย่าง แต่สิ่งนี้จะอธิบายความแตกต่างที่มีประโยชน์มากขึ้นในสองโครงสร้าง
Kamil Drakari

3
ว้าวคุณได้คะแนนโหวตมากกว่า Jon Skeet ที่โด่งดัง
machine_1

21

นี่คือคุณสมบัติภาษา C # 6

ตัวอย่างแรก

public int Number { get; } = 0

ตัวอย่างแรกเป็นสถานที่ให้บริการอัตโนมัติทะเยอทะยานเท่านั้น เขตข้อมูลสำรองของคุณสมบัติอัตโนมัติ getter เท่านั้นจะถูกประกาศโดยนัยว่าเป็นแบบอ่านอย่างเดียว

ตัวอย่างที่สอง

public int Number => 0;

และเป็นตัวอย่างที่สองคือร่างกายแสดงออกสมาชิกฟังก์ชั่นคุณสมบัติเหมือน โปรดทราบว่าไม่มีgetคำหลักใด ๆ: มันมีนัยโดยการใช้ไวยากรณ์ของร่างกายนิพจน์

ทั้งสองเป็นแบบอ่านอย่างเดียว


5
... แต่ตามที่ Jon Skeet อธิบายคุณสามารถเปลี่ยนค่าที่ค่าแรกคืน
Martin Bonner สนับสนุน Monica

2
@MartinBonner ... แต่เฉพาะในนวกรรมิกเท่านั้น
Dennis Kuypers

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