คลาสกับโมดูลใน VB.NET


157

มันถือว่าเป็นแนวปฏิบัติที่ยอมรับได้ในการใช้ Modules แทนที่จะเป็น Classes ที่มีฟังก์ชั่นสมาชิกที่ใช้ร่วมกันใน VB.NET หรือไม่?

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

ฉันอยากรู้ว่าคุณมีความคิดเห็นหรือความชอบใด ๆ ไม่ทางใดก็ทางหนึ่ง


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

คำตอบ:


207

Modules คือ VB คู่กับstaticคลาสC # เมื่อชั้นเรียนของคุณได้รับการออกแบบ แต่เพียงผู้เดียวสำหรับการทำงานของผู้ช่วยและวิธีการขยายและคุณไม่ต้องการให้มรดกและinstantiationModuleคุณใช้

โดยวิธีการที่ใช้Moduleไม่ได้เป็นอัตนัยจริงๆและมันก็ไม่ได้เลิก แน่นอนคุณต้องใช้Moduleเมื่อเหมาะสม .NET Framework ทำเองหลายครั้ง ( System.Linq.Enumerableเช่น) ในการประกาศเมธอดส่วนขยายจำเป็นต้องใช้Modules


7
ค่อนข้างถูกต้องแม้ว่าฉันจะสามารถใช้ตัวสร้างส่วนตัวเพื่อป้องกันการสร้างอินสแตนซ์และปรับแต่ง NotInheritable น่าเกลียดกว่าเล็กน้อยโมดูลเก่า แต่มีผลเหมือนกัน ขอบคุณสำหรับตัวชี้ไปยังการใช้โมดูลใน Framework; ฉันจะดูว่า
Tom Juergens

8
ภายใต้ประทุนพวกเขาจะถูกคอมไพล์ไปยังคลาสที่มีแอตทริบิวต์ [StandardModule] นอกจากนี้การใช้โมดูลบังคับให้คุณไม่ต้องมีสิ่งที่ไม่แบ่งปันซึ่งเป็นสิ่งที่ดี
Mehrdad Afshari

18
โมดูลไม่เหมือนกับคลาสสแตติกใน C # วิธีการในโมดูลเป็นสากลอย่างมีประสิทธิภาพถ้าพวกเขาอยู่ใน namespace ที่นำเข้า
JaredPar

2
@ JaredPar: ข้อความของฉันอาจไม่ดี ฉันควรได้กล่าว VB คู่หูคลาส C # คงที่ จากคำสั่งนั้นฉันหมายถึงการพูดว่าการใช้โมดูลเหมาะสมที่คุณจะเขียนคลาสคงที่ใน C #
Mehrdad Afshari

3
@Chiwda ดูmsdn.microsoft.com/en-us/library/bb384936.aspx : "วิธีการขยายสามารถประกาศได้ภายในโมดูลเท่านั้น"
Mehrdad Afshari

34

ฉันคิดว่ามันเป็นความคิดที่ดีที่จะหลีกเลี่ยงโมดูลยกเว้นว่าคุณใส่มันลงในเนมสเปซที่แยกต่างหาก เพราะในวิธี Intellisense ในโมดูลจะมองเห็นได้จากทุกที่ในเนมสเปซนั้น

ดังนั้นแทนที่จะModuleName.MyMethod()คุณท้ายด้วยMyMethod()ป๊อปอัพในทุกที่และทุกชนิดของการเลิกนี้การห่อหุ้ม (อย่างน้อยในระดับการเขียนโปรแกรม)

นั่นเป็นเหตุผลที่ฉันพยายามสร้าง Class ด้วยวิธีการที่ใช้ร่วมกันอยู่เสมอดูเหมือนจะดีขึ้นมาก


7
ตกลงฉันกำลังทำงานกับโปรแกรมเก่าในขณะนี้ (อาจเป็นพอร์ต VB6 ถึง VB.NET 1) ที่มีคลาสและโมดูล มีตัวแปรทั่วโลกหลายร้อยตัวย่อยและฟังก์ชั่นในโมดูลที่แตกต่างกันประมาณสิบและมันเป็นนรกค้นหาสิ่งที่มาและวิธีการที่ได้รับการแก้ไข
yu_ominae

ตกลงนี่เก่ามาก แต่เกี่ยวข้องกับคำถามของฉัน ฉันไม่ใช่คน VB แต่ฉันต้องทำงานกับมัน ฉันพยายามที่จะทำลายชั้นเรียนขนาดใหญ่ (> 46,000 บรรทัด) เพราะ IntelliSense / ReSharper เพิ่งจะตาย ฉันได้พบการใช้ Modules และเพียงแค่ดึงเอาฟังก์ชั่นชิ้นใหญ่ ๆ ลงในโมดูลของตัวเองดูเหมือนว่าจะใช้งานได้ แต่ฉันสงสัยว่าฉันควรจะให้เนมสเปซของแต่ละโมดูลเป็นของตัวเองหรือไม่ นั่นจำเป็นไหม เช่นจะเร่งความเร็ว IntelliSense เพียงแค่ใช้ Modules หรือ Namespaces จะช่วยเหลือเพิ่มเติมหรือไม่
codah

27

โมดูลไม่ได้ถูกคัดค้านและใช้อย่างมากในภาษา VB เป็นวิธีเดียวที่อินสแตนซ์จะใช้วิธีการขยายใน VB.Net

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

ต่อไปนี้เป็นตัวอย่างด่วนที่ฉันใช้บ่อยๆเมื่อเขียนโค้ด VB ที่เชื่อมโยงกับอินเตอร์เฟส COM ดิบ

Module Interop
  Public Function Succeeded(ByVal hr as Integer) As Boolean
    ...
  End Function

  Public Function Failed(ByVal hr As Integer) As Boolean
    ...
  End Function
End Module

Class SomeClass
  Sub Foo()
    Dim hr = CallSomeHrMethod()
    if Succeeded(hr) then
      ..
    End If
  End Sub
End Class

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

12

Moduleมันเป็นที่ยอมรับที่จะใช้ ไม่ได้ใช้แทนสำหรับModule ตอบสนองวัตถุประสงค์ของตัวเอง วัตถุประสงค์ของการใช้เป็นภาชนะสำหรับClassModuleModule

  • วิธีการขยาย
  • ตัวแปรที่ไม่เฉพาะเจาะจงใด ๆClassหรือ
  • ตัวแปรที่ไม่เหมาะสมในข้อใดข้อClassหนึ่ง

Moduleไม่เหมือนClassเมื่อคุณไม่สามารถ

  • ได้รับมรดกจากModule,
  • ใช้InterfaceกับModule,
  • Moduleมิได้สร้างตัวอย่างของหนึ่ง

สิ่งใดใน a Moduleสามารถเข้าถึงได้โดยตรงภายในModuleแอสเซมบลีโดยไม่อ้างอิงถึงModuleชื่อ โดยค่าเริ่มต้นระดับการเข้าถึงสำหรับเป็นModuleFriend


11

การเรียนการสอน

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

โมดูล

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

6

เมื่อหนึ่งในคลาส VB.NET ของฉันมีสมาชิกที่ใช้ร่วมกันทั้งหมดฉันจะแปลงเป็นโมดูลที่มีเนมสเปซที่ตรงกัน (หรือเหมาะสม) หรือฉันทำให้คลาสไม่สามารถสืบทอดได้และไม่สามารถสร้างได้:

Public NotInheritable Class MyClass1

   Private Sub New()
      'Contains only shared members.
      'Private constructor means the class cannot be instantiated.
   End Sub

End Class

3
และนี่คือไวยากรณ์สำหรับโมดูล namespaced: Imports <whatever>ถ้าคุณมีการนำเข้าใด ๆNamespace MyCoolModule, Public Module MyCoolModule<สมาชิกโดยไม่ต้อง >Shared , End ModuleEnd Namespace
Rory O'Kane

0

โมดูลเป็นสิ่งที่ดีสำหรับการจัดเก็บ enums และตัวแปรโกลบอลค่าคงที่และฟังก์ชันที่ใช้ร่วม มันเป็นสิ่งที่ดีมากและฉันมักจะใช้มัน ตัวแปรที่ประกาศเป็น acros ที่มองเห็นได้ทั้งโครงการ


0

คุณต้องใช้โมดูล (แทนที่จะเป็นคลาส) หากคุณกำลังสร้างวิธีการขยาย ใน VB.NET ฉันไม่รู้ตัวเลือกอื่น

การทนต่อโมดูลด้วยตัวเองฉันใช้เวลาสองสามชั่วโมงไร้ค่าในการพยายามหาวิธีเพิ่มรหัสสำเร็จรูปบางส่วนเพื่อแก้ไขชุดประกอบแบบฝังตัวในที่เดียวเท่านั้นที่จะพบว่าSub New()(Module) และShared Sub New()(Class) เทียบเท่ากัน (ผมไม่ได้รู้ว่ามีเป็น callable Sub New()ในโมดูล!)

ดังนั้นฉันเพิ่งโยนEmbeddedAssembly.LoadและAddHandler AppDomain.CurrentDomain.AssemblyResolveเส้นในนั้นและบ๊อบกลายเป็นลุงของฉัน

ภาคผนวก : ฉันยังไม่ได้ตรวจสอบมัน 100% แต่ฉันมี inkling ที่Sub New()ทำงานในลำดับที่แตกต่างกันใน Module กว่า Class เพียงไปตามความจริงที่ว่าฉันต้องย้ายประกาศไปยังวิธีการจากภายในเพื่อหลีกเลี่ยง ข้อผิดพลาด

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