เหตุใดจึงใช้คลาสบางส่วน


72

ในความเข้าใจของฉันpartialคำหลักไม่ทำอะไรเลยนอกจากอนุญาตให้แบ่งคลาสระหว่างไฟล์ต้นฉบับหลาย ๆ ไฟล์ มีเหตุผลใดที่จะทำสิ่งนี้นอกเหนือจากการจัดระเบียบรหัสหรือไม่ ฉันเคยเห็นมันใช้สำหรับสิ่งนั้นในคลาส UI ที่สร้างขึ้น

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


10
มันไม่ได้เป็น "คำหลักทั้งหมด" เช่นกัน มันเป็นคำหลักตามบริบท partialเพียง classแต่หมายถึงบางสิ่งบางอย่างเมื่อมันมาก่อน คุณสามารถใช้มันเป็นชื่อของตัวระบุในส่วนอื่น ๆ ของรหัส ฯลฯ
Dean Harding

4
หากคุณใช้พวกเขาและไม่ใช่รหัสที่สร้างขึ้นฉันเกลียดคุณ ไม่ใช่คุณเป็นการส่วนตัว แต่โดยทั่วไปคุณ ฉันเกลียดการตามล่ารหัสผ่านคลาสบางส่วน
Steven Evers

3
ไม่ใช่เรื่องยากที่จะ "ค้นหารหัส" วิธีการเรียนทั้งหมดยังคงปรากฏในรายการแบบหล่นลงใน VS ไม่ว่าส่วนใดของส่วนที่คุณกำลังดูอยู่ การนาวิเกตโค้ดอื่น ๆ ก็ใช้ได้เช่นกัน (เช่นการนำทางแบบ "ฉลาด" R # หรือ shift-ctrl-f เก่า ๆ ที่ดี
Steve

2
มันเป็นความเข้าใจผิดที่คลาสบางส่วนต้องอยู่ในไฟล์แยกกัน
Bart

คำตอบ:


110

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

มันไม่ได้เกี่ยวกับ UI เท่านั้น แต่ยังรวมถึงเทคโนโลยีอื่น ๆ เช่น Linq-To-Sql หรือ Entity Framework ใช้สิ่งนี้ค่อนข้างหนัก


44
นอกจากนี้ยังช่วยให้คุณสามารถเก็บรหัสของคุณภายใต้การควบคุมเวอร์ชันในขณะที่ปล่อยให้รหัสที่สร้างไว้ไม่อยู่ในการควบคุมเวอร์ชัน
Frank Shearar

3
จุดดีฉันไม่เคยคิดอย่างนั้น ฉันเพิ่งเห็นว่าถูกใช้ในทางที่ผิด วิธีสำหรับโปรแกรมเมอร์ (lousy) เพื่อให้ขนาดไฟล์สามารถจัดการได้
Martin Wickman

1
ตัวอย่างที่ดีที่สุดที่ฉันใช้คือ:) บริบทของ Linq ไปเป็น SQL ที่คุณต้องการขยายคลาส; b) เพื่อขยายคลาสที่ส่งผ่านจากเว็บเซอร์วิส ไม่ว่าในกรณีนี้จะเป็นการละเมิดหรือเป็นวิธีการจัดการขนาดไฟล์ ... ฉันไม่พอใจอย่างยิ่งที่จะเห็นมันใช้ในลักษณะนั้น (และจะทำตามขั้นตอน ... )
Murph

3
คลาส WinForm ใช้เพื่อซ่อนรหัสของนักออกแบบทั้งหมดที่สร้างตัวควบคุม (โดยเฉพาะอย่างยิ่งที่สำคัญเนื่องจากนักออกแบบชอบที่จะสุ่มเรียงลำดับรหัสทั้งหมดที่สร้างขึ้นใหม่ทำให้เกิดความยุ่งเหยิงอย่างมากเมื่อ diff / blaming) และหากคุณทำงานกับ XML เครื่องมือ XSD สามารถ สร้างคลาสบางส่วนออกจากไฟล์สคีอีกครั้งช่วยให้คุณสามารถแยกรหัสของคุณจากการเรียงลำดับที่สร้างขึ้นอัตโนมัติ
Dan Neely

2
@MartinWickman ไม่จำเป็นต้องมีหมัด มันเป็นจุดเริ่มต้นที่ดีสำหรับการรื้อฟื้นวัตถุพระเจ้าในรหัสดั้งเดิม พยายามที่จะล้างภูมิทัศน์โดยแบ่งชั้นเรียนขนาดใหญ่เป็นไฟล์แยกกันก่อน (ฉันรู้ว่าความคิดเห็นของคุณเก่ามาก)
Konrad Morawski

26

อย่างที่คุณพูดมันมักจะถูกใช้เพื่อแยกรหัสที่สร้างขึ้น บ่อยครั้งที่ไม่มีอะไรเกี่ยวข้องกับขนาดของคลาส / ไฟล์

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

อีกพื้นที่ที่ฉันใช้มันเป็นที่ที่คลาสใช้อินเทอร์เฟซหลายอย่างมันค่อนข้างดีที่จะแยกการใช้งานในการแยกไฟล์แม้ว่ามันจะเป็นเรื่องของความชอบส่วนตัวฉันไม่เคยเห็นมาตรฐานการเข้ารหัสใด ๆ ที่ต้องการ ( หรือป้องกัน) สิ่งนี้


9
ฉันไม่เคยคิดที่จะใช้งาน class partials เพื่อแยกการใช้งานอินเตอร์เฟสนั่นเป็นแนวคิดที่ยอดเยี่ยม
Mark Booth

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

19

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

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


1
ฉันสามารถดูว่ามันจะมีประโยชน์อย่างไร ไม่ว่าจะเป็นเหตุผลในการเป็นภาษาหรือไม่ ... ฉันไม่รู้ เครื่องสร้างรหัสเป็นอีกเรื่องหนึ่ง
Michael K

2
ใช่ไม่ใช่เหตุผลในการใช้ภาษา แต่เป็นวิธีที่น่าสนใจในการใช้

18

ฉันสามารถนึกถึงสถานการณ์ที่มีประโยชน์ไม่กี่อย่างที่ผู้เข้าร่วมแสดงความคิดเห็นส่วนใหญ่ฉันใช้ตัวเองในโครงการของฉัน:

  • ในการแยกรหัสที่สร้างจากเครื่องมือ / IDE / Designerออกจากรหัสที่คุณกำลังบำรุงรักษา ตัวอย่างที่ดีคือForm.Designer.csไฟล์ที่มีรหัสที่ผู้ออกแบบสร้างขึ้นสำหรับ windows ในรูปแบบแอปพลิเคชัน รูปแบบ. NET อื่น ๆ อีกมากมายยังมีรหัสบางส่วนที่สร้างขึ้นด้วยเครื่องมือซึ่งสามารถสร้างใหม่ได้เมื่อคุณสร้างโครงการของคุณดังนั้นการเปลี่ยนแปลงที่กำหนดเองทั้งหมดของคุณจะถูกกวาดออกไป การแยกจะช่วยให้คุณรักษารหัสและการเปลี่ยนแปลงที่ปลอดภัยจากการแก้ไขอัตโนมัติดังกล่าว

  • เมื่อคุณใช้หลายอินเตอร์เฟสพร้อมกับรหัสจำนวนมากในการนำไปใช้งาน {Class}.{Interface}.csฉันมักจะใช้ไฟล์บางส่วนแยกต่างหากสำหรับแต่ละอินเตอร์เฟซที่ดังกล่าวตั้งชื่อมันเช่นนี้ มันง่ายสำหรับฉันที่จะเห็นใน IDE ที่อินเตอร์เฟส{Class}กำลังใช้งานและวิธีการ

  • เมื่อคลาสต้องมีคลาสที่ซ้อนกันหนึ่งคลาสขึ้นไปโดยเฉพาะอย่างยิ่งที่มีโค้ดเพียงพอที่จะใส่ลงในไฟล์แยกต่างหาก ฉันจะยึดตามรูปแบบข้างต้นและใช้หลักการ{Class}.{NestedClass}.csตั้งชื่อสำหรับแต่ละคลาสที่ซ้อนกัน การปฏิบัติที่คล้ายกันเป็นที่กล่าวถึงแล้วโดยคำตอบของ Virtlink

  • เมื่อผมเขียนstaticเรียนซึ่งจะถือวิธีการขยาย มันมักจะเป็นกรณีที่จะให้ตรรกะวิธีการขยายเดียวกันกับคลาสหรืออินเทอร์เฟซที่คล้ายกัน - ตัวอย่างเช่นReverseในคอลเลกชันทั่วไปและที่ไม่ใช่ทั่วไป ฉันจะใส่วิธีการขยายทั้งหมดสำหรับชั้นเดียวหรืออินเตอร์เฟซในส่วนที่แยกจากกันของระดับคงที่ ตัวอย่างเช่นฉันมีวิธีการขยายทั้งหมดสำหรับIListอินเทอร์เฟซในที่เดียวและวิธีการเดียวกับที่ใช้IList<T>ในไฟล์อื่น อีกวิธีหนึ่งคือการวางวิธีการเดียวกัน (overloads ทั้งหมด) ในส่วนเดียวกันโดยมีคลาสที่เป็นไปได้ทั้งหมดสำหรับthisพารามิเตอร์ - เช่นเดียวกับที่มีReverseการใช้งานในหนึ่งไฟล์ มันขึ้นอยู่กับว่าใครจะแสดงให้เห็นถึงการแยกในแง่ของปริมาณโค้ดหรือการประชุมภายในบางอย่างที่คุณหรือองค์กรของคุณอาจติดอยู่

  • ฉันไม่ได้ใช้สิ่งนี้ แต่ฉันเห็นกลุ่มคน C / C ++ ชอบวิธีที่ฉันจะอธิบายที่นี่: สร้างบางส่วนสำหรับชั้นเรียนด้วยวิธีการบางส่วนเท่านั้น สิ่งนี้คล้ายกับวิธี C / C ++ เพื่อกำหนดอินเตอร์เฟสและแยกการประกาศเมธอดจากการอิมพลีเมนต์

  • แยกโดยหมดจดกังวลตรรกะ หากคุณทำงานกับคลาสขนาดใหญ่ที่รวมการดำเนินการทางตรรกะมากกว่าหนึ่งชุดในตัวของมันเองคุณสามารถแยกแต่ละรหัสที่เกี่ยวข้องกับเหตุผลออกเป็นส่วนย่อยได้ โดยปกติการดำรงอยู่ของชั้นเรียนดังกล่าวเป็นกับการแยกของความกังวลหลักการ แต่มันเป็นที่สังเกต oftenly ชีวิตจริงกรณีโดยเฉพาะอย่างยิ่งสำหรับ codebases เก่า ผู้ใช้เพื่อน Steve Evers ได้กล่าวถึงพวกเขาในคำตอบของคำถามนี้ซึ่งอ้างอิงถึงพวกเขาด้วยชื่อวัตถุพระเจ้า. โดยส่วนตัวแล้วฉันจะใช้วิธีการของคลาสบางส่วนเพื่อแยกรหัสก่อนที่จะทำการ refactor ของไฟล์ที่มีขนาดใหญ่จริงๆเพื่อให้งานของฉันง่ายขึ้น สิ่งนี้จะลดความขัดแย้งที่ฉันอาจเกิดขึ้นเมื่อระบบการกำหนดเวอร์ชันเช่น SVN เกี่ยวข้อง


14

ฉันไม่เห็นใครพูดถึง: ฉันใช้partialเพื่อวางคลาสที่ซ้อนกันในไฟล์ของตนเอง

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

นี่ก็หมายความว่าคลาสที่NestedClassอยู่ภายในMyClassจะมีไฟล์เป็นของตัวเองในโครงการของฉัน: MyClass.NestedClass.cs.

partial class MyClass
{
    private class NestedClass
    {
        // ...
    }
}

1
ฉันสงสัยว่าทำไมใครคนหนึ่งถึงลงคะแนนคำตอบนี้ การปฏิบัติดังกล่าวไม่ใช่การต่อต้านแบบและมันจะทำให้เกิดปัญหาใด ๆ ที่ฉันรู้
Ivaylo Slavov

1
นอกจากนี้ยังแก้ไขปัญหาของการรักษาไฟล์คลาสเล็ก ๆ (ในแง่ของบรรทัดของโค้ด) ในขณะที่ยังคงอนุญาตให้มีการห่อหุ้มโค้ดที่เหมาะสมซึ่งเป็นของคลาสภายใน
redcalx

10

ด้วยข้อยกเว้นของการใช้รหัสที่สร้างขึ้นที่ฉันได้เพียงเท่าที่เคยเห็นพวกเขาใช้ในความพยายามที่จะปกปิดสำหรับวัตถุพระเจ้า การพยายามที่จะทำความเข้าใจกับ codebase ใหม่หรือนำทางผ่านหลาย ๆ ไฟล์ที่เป็นวัตถุเดียวกันนั้นน่ารำคาญมาก

ดังนั้นเมื่อคุณถามWhy use partial classes?ฉันตอบ: ถ้าคุณใช้รหัสที่สร้างขึ้นไม่


+1 นี่เป็นครั้งแรกที่ฉันเห็นวัตถุประเภทนี้เรียกว่าชื่อ (วัตถุพระเจ้า) และเป็นทางการแม้แต่ มันไม่สายเกินไปที่จะเรียนรู้สิ่งใหม่
Ivaylo Slavov

6

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

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

1

นอกจากนี้ยังมีสถานที่บางแห่งที่มีการประกาศคลาสที่สร้างขึ้น / โดยนัยบางส่วนดังนั้นหาก Dev ต้องการขยายพวกเขาพวกเขาสามารถเข้าถึงได้อย่างเต็มที่โดยไม่ต้องยุ่งเกี่ยวกับการสืบทอดและการเอาชนะเหนือสถานที่ทั้งหมด ดูคลาสที่สร้างขึ้นในพื้นที่ temp asp.net หลังจากที่คุณเรียกใช้เว็บไซต์ webforms เป็นครั้งแรกภายใต้ IIS ถ้าคุณต้องการลองจับตัวอย่าง


1

ฉันคิดว่ามันสกปรกสำหรับพวกเขา

สมมติว่าคุณมีบางคลาสที่ต้องการฟังก์ชั่นทั่วไป แต่คุณไม่ต้องการแทรกฟังก์ชันการทำงานนั้นลงในห่วงโซ่การสืบทอดด้านบน หรือคุณมีชุดคลาสที่ใช้คลาสตัวช่วยทั่วไป

โดยทั่วไปคุณต้องการที่จะทำหลายมรดก แต่ C # ไม่เหมือนกัน ดังนั้นสิ่งที่คุณทำคือใช้บางส่วนเพื่อสร้างสิ่งที่เป็น #include ใน C / C ++;

ใส่ฟังก์ชันการทำงานทั้งหมดลงในคลาสหรือใช้คลาสตัวช่วย จากนั้นคัดลอกตัวช่วย X คูณและเปลี่ยนชื่อเป็นคลาส A, B, C บางส่วน และใส่คลาส A, B, C บางส่วน

คำเตือน: ใช่นี่คือความชั่วร้าย อย่าทำอย่างนั้นโดยเฉพาะถ้ามันจะทำให้คนอื่นโกรธคุณ


mixins สิ่งนี้สามารถใช้ร่วมกับ T4 เพื่อหลีกเลี่ยงการคัดลอกด้วยตนเอง ...
Peter Taylor

ตามที่ระบุไว้นี้คล้ายกับ mixins อย่างใกล้ชิด อย่างไรก็ตามคุณกำลังเข้าใกล้แนวคิดที่เรียกว่า "ลักษณะ" และพวกเขาจะจัดการกับสิ่งที่คุณพยายามที่จะบรรลุได้อย่างปลอดภัย ฉันมีคำอธิบายภาษาผู้ไม่เชื่อเรื่องพระเจ้าที่publius-ovidius.livejournal.com/314737.html ฉันมองหาการใช้งานที่สะอาดสำหรับ C # แต่ยังไม่เคยเห็น
Ovid
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.