เมื่อใดที่จะใช้ [บริสุทธิ์] บนตัวสร้าง?


19

ฉันกำลังเรียนรู้เกี่ยวกับสัญญารหัสใน. NET และฉันพยายามเข้าใจแนวคิดของผู้สร้างที่บริสุทธิ์ สัญญารหัสเอกสารฯ :

วิธีการทั้งหมดที่เรียกว่าภายในสัญญาจะต้องบริสุทธิ์ นั่นคือพวกเขาจะต้องไม่ปรับปรุงสถานะก่อนหน้าใด ๆ วิธีบริสุทธิ์ได้รับอนุญาตให้แก้ไขวัตถุที่สร้างขึ้นหลังจากเข้าสู่วิธีบริสุทธิ์

และPureAttributeเอกสารประกอบฯ :

บ่งชี้ว่าชนิดหรือเมธอดนั้นบริสุทธิ์นั่นคือมันไม่ได้ทำการเปลี่ยนแปลงสถานะใด ๆ ที่มองเห็นได้

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

public class Foo
{
    public int Value { get; set; }

    public Foo(int value) {
        this.Value = value;
    }
}

คอนสตรัคเตอร์นี้เห็นได้ชัดว่ามีผลต่อสถานะของFooวัตถุใหม่แต่ไม่มีผลข้างเคียงอื่น ๆ (เช่นมันไม่ได้ใช้พารามิเตอร์ใด ๆ หรือเรียกวิธีการที่ไม่บริสุทธิ์) เป็นผู้สมัคร[Pure]หรือไม่? อะไรคือความสำคัญของการวางแอ[Pure]ททริบิวต์ลงในคอนสตรัคเตอร์และเมื่อไหร่ที่ฉันควรทำสิ่งนี้ในโค้ดของตัวเอง?

คำตอบ:


14

คุณตกแต่งวิธีด้วย[Pure]:

  • หากวิธีการไม่มีผลข้างเคียง ตัวอย่างเช่นหากวิธีการเข้าถึงฐานข้อมูลและแก้ไขหรือผลลัพธ์ขึ้นอยู่กับฐานข้อมูลมันไม่บริสุทธิ์

  • และถ้าคุณคาดว่าจะใช้มันในสัญญาโค้ด ตัวอย่างเช่นหากวิธีนี้บริสุทธิ์แต่คุณไม่มีความตั้งใจที่จะใช้ในสัญญารหัสการเพิ่ม[Pure]จะไม่มีประโยชน์และจะไม่ทำให้โค้ดของคุณเร็วขึ้น

เท่าที่มันเกี่ยวข้องกับคอนสตรัคเตอร์ดูเหมือนว่าพวกเขาจะถือว่าบริสุทธิ์ใน. NET และไม่ต้องการคุณลักษณะที่ชัดเจน ฉันดูตัวสร้างหลายตัวในซอร์ส. NET Framework เช่นDateTimeและพวกเขาไม่มี[Pure]คุณสมบัติ

ฉันคิดว่าจะทำด้วยเหตุผลหลายประการ:

  • มันอาจจะเป็นไปไม่ได้ที่จะเขียนตัวสร้างแบบไร้พารามิเตอร์ที่มี[Pure]แอ็ตทริบิวต์เพื่อใช้คลาส / โครงสร้างในสัญญา

  • บางคนเช่นStringไม่มีตัวสร้างที่ชัดเจน

  • ตัวสร้างได้รับการดูแลเป็นพิเศษแม้จะอยู่นอกรหัสสัญญา ตัวอย่างเช่นคุณไม่ได้คาดหวังว่าจะโยนข้อยกเว้นในพวกเขา

  • [Pure]เป็นเพียงการประชุมที่นี่เพื่อทำให้ชีวิตของคุณง่ายขึ้น แต่ไม่มีการตรวจสอบที่เกิดขึ้นจริงเพื่อให้แน่ใจว่าวิธีการตกแต่งด้วยคุณลักษณะนี้บริสุทธิ์ void DestroyDatabase()อาจได้รับการตกแต่งว่าบริสุทธิ์และสัญญารหัสจะไม่สังเกตเห็นอะไรผิดปกติ

    ปัจจุบันไม่มีองค์ประกอบของสัญญารหัสที่ตรวจสอบว่าวิธีการที่ประกาศบริสุทธิ์นั้นบริสุทธิ์หรือไม่ ดังนั้นหากโปรแกรมเมอร์ตกแต่งวิธีด้วย [บริสุทธิ์] ก็เชื่อว่า

    จากCode Contracts # 5: ความบริสุทธิ์ของวิธีการ

  • .NET Framework นั้นมีคอนสตรัคเตอร์ที่ไม่บริสุทธิ์ ตัวอย่างเช่นList<T>(IEnumerable<T> collection)ไม่จริงถ้าวนลูปผ่านการรวบรวมมีผลข้างเคียง

  • การตะโกนสัญญานั้นง่ายมาก ฉันสามารถจินตนาการสัญญาเช่นContract.Requires(!string.IsNullOrEmpty(name))ดังนั้นจึงมีเหตุผลที่ดีที่จะประกาศคงที่string.IsNullOrEmptyบริสุทธิ์

    ในทางกลับกันหากคุณต้องการStringBuilderสร้างสตริงคุณจะต้องตรวจสอบบางสิ่งโดยเรียกวิธีการอินสแตนซ์ของชั้นธุรกิจของคุณคุณอาจใช้สัญญาผิดวัตถุประสงค์ นั่นเป็นเหตุผลที่StringBuilder.ToStringไม่ได้ระบุว่าบริสุทธิ์แม้ว่าอาจจะเป็น (มันคืออะไร)


สัญญาโค้ดจำนวนมากเกี่ยวกับประเภทของระบบจะถูกสันนิษฐานโดยผู้ตรวจสอบสัญญารวมถึง " วิธีการใด ๆ ที่ชื่อที่ผ่านการรับรองโดยสมบูรณ์เริ่มต้นด้วย" System.Diagnostics.Contracts.Contract "," System.String "," System.IO.Path "หรือ" ระบบ .Type " " น่าเสียดายที่ฉันไม่แน่ใจว่าการดูประเภท. NET นั้นมีประโยชน์มากเกินไปหรือไม่เมื่อพูดถึงสัญญาโค้ด
pswg

3
ความบริสุทธิ์เป็นหนึ่งในสิ่งต่าง ๆ ที่ทุกคนเรียกรหัสก็ต้องบริสุทธิ์หรือผู้โทรไม่ได้ "บริสุทธิ์" ฉันคิดว่ามันยากที่จะเชื่อว่าผู้สร้างทั้งหมดถือว่าบริสุทธิ์โดยปริยาย
Frank Hileman

@ FrankHileman: ฉันด้วย ฉันไม่มีคอมไพเลอร์ C # ในตอนนี้ แต่มันก็เพียงพอแล้วที่จะเขียนคลาสด้วยตัวสร้างและไม่มี[Pure]แอ็ตทริบิวต์และใช้ที่อื่นในสัญญาเพื่อให้ได้คำตอบที่ชัดเจน
Arseni Mourzenko

1

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


ดังนั้นคอนสตรัคเตอร์บริสุทธิ์เป็นวิธีการบริสุทธิ์ที่ได้รับอนุญาตให้เปลี่ยนสถานะของคลาสปัจจุบันตราบใดที่มันเป็นไปตามเงื่อนไขอื่น ๆ ของการเป็นบริสุทธิ์? BTW สถานที่ให้บริการที่ไม่แน่นอนเพราะฉันต้องการที่จะเน้นว่าชั้นนี้ตัวเองไม่บริสุทธิ์
pswg

@pswg: คุณสร้างคำถามที่น่าสนใจซึ่งอาจต้องตอบโดย Microsoft สมมติว่า Constructor เรียกใช้เมธอดที่แก้ไขคุณสมบัติที่ไม่แน่นอน ตัวสร้างจะยังคงบริสุทธิ์หรือไม่ ฉันคิดว่าในทางเทคนิคแล้วจะไม่เป็นเช่นนั้นแม้ว่าการดัดแปลงจะเป็น "มองไม่เห็น" สำหรับผู้ดูภายนอก เนื่องจากไม่มีรหัสอื่นที่ถูกเรียกใช้ในตัวอย่างดั้งเดิมของคุณจึงต้องบริสุทธิ์โดยนิยามใด ๆ ที่ฉันนึกออก
Frank Hileman

@pswg: ยกเว้นว่าชุดคุณสมบัติเป็นวิธีการโทร .. ฉันคิดว่าคุณควรถามในฟอรัม MSDN
Frank Hileman

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

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