问题
I am trying to call a certain method (say method called "Mood") associated with a Enum value (e.g. Enum WorkDay : Monday, Tuesday, Wednesday etc.).
I can obviously do a select case and call certain methods as below.
Public Enum WorkDay
Monday
Tuesday
Wednesday
Thursday
Friday
End Enum
Dim CurrentDay As Class1.WorkDay = Class1.WorkDay.Monday
Select Case CurrentDay
Case Class1.WorkDay.Monday
Function_Monday()
Case Class1.WorkDay.Tuesday
Method_Tuesday()
Case Class1.WorkDay.Wednesday
Method_Wednesday()
Case Class1.WorkDay.Thursday
Method_Thursday()
Case Class1.WorkDay.Friday
Method_Friday()
End Select
However, I have seen it done previously using an interface for the Enum to call methods in different classes. This means it's scalable by simply adding in a new class for newer Enum types, and therefore don't need to add in extra Case legs for newer Enum types (e.g. Saturday and Sunday). Can anyone possibly give me some template code for this Enum interface, as I just can't recreate it. I'm missing something!
回答1:
This is easily handled by the Typesafe Enum Pattern, see this article (and the previous one linked from it) give a good overview.
Enhancing the Typesafe Enum Pattern
Here is an example of how your specific issue could be handled by this pattern (converted to VB .NET):
Public Class WorkDay
' private constructor
Private Sub New(day As String)
Me.Day = day
End Sub
Public Day As WorkDay
Public Sub DoDayJob()
' do whatever need done for that day of the week
End Sub
Public Shared Monday As New WorkDay("Monday")
Public Shared Tuesday As New WorkDay("Tuesday")
Public Shared Wednesday As New WorkDay("Wednesday")
Public Shared Thursday As New WorkDay("Thursday")
Public Shared Friday As New WorkDay("Friday")
End Class
'used like this (to assign the 'Monday' value)
Dim day = Workday.Monday
I added a single method, however the class can be as complex as it needs to be.
回答2:
Is it not possible for you to pass the enum to your method? And execute logic based on that?
Some thing like the following
Function ProcessDay(DayOfWeek as WorkDay) As IWorkDay
Select Case DayOfWeek
Case WorkDay.Monday
Return <<class that inherits IWorkDay>>
Case WorkDay.Tuesday
Return <<class that inherits IWorkDay>>
End Select
End Function
回答3:
This seems to work for me - rather than have a Select Case statement This loop iterates through each Enum value and compares it to the Enum Variable and executes the method with the appropriate name that matches the Enum name
For Each day As class1.WorkDay In System.Enum.GetValues(GetType(class1.WorkDay))
If CurrentDay = day Then
CallByName(Me, "Method_" & [Enum].GetName(GetType(class1.WorkDay), day), CallType.Method, Nothing)
End If
Next
You may need to change a few things depending on how your code is written, but the basic idea is there.
回答4:
Based on the description of your goals of allowing for future Enum values and/or classes, a simple solution is to use a delegate dictionary keyed on the base Enum type.
Assume a class declaration like this:
Public Class Class1
Public Enum WorkDay
Monday
Tuesday
Wednesday
Thursday
Friday
End Enum
Public Shared Sub Method_Monday()
End Sub
Public Shared Sub Method_Tuesday()
End Sub
Public Shared Sub Method_Wednesday()
End Sub
Public Shared Sub Method_Thursday()
End Sub
Public Shared Sub Method_Friday()
End Sub
End Class
Public Class Class2
Public Enum NotWorkDay
Saturday
Sunday
End Enum
Public Shared Sub Method_Saturday()
End Sub
Public Shared Sub Method_Sunday()
End Sub
End Class
Then class (a WinForm in this case) that uses the above classes, would look something like this:
Public Class Form1
' declare the delegate dictionary
Private WorkMethods As New Dictionary(Of [Enum], Action)
Public Sub New()
InitializeComponent()
SetWorkMethods()
End Sub
Private Sub SetWorkMethods()
'fill the dictionary with the needed actions
WorkMethods.Add(Class1.WorkDay.Monday, New Action(AddressOf Class1.Method_Monday))
WorkMethods.Add(Class1.WorkDay.Tuesday, New Action(AddressOf Class1.Method_Tuesday))
WorkMethods.Add(Class1.WorkDay.Wednesday, New Action(AddressOf Class1.Method_Wednesday))
WorkMethods.Add(Class1.WorkDay.Thursday, New Action(AddressOf Class1.Method_Thursday))
WorkMethods.Add(Class1.WorkDay.Friday, New Action(AddressOf Class1.Method_Friday))
WorkMethods.Add(Class2.NotWorkDay.Saturday, New Action(AddressOf Class2.Method_Saturday))
WorkMethods.Add(Class2.NotWorkDay.Sunday, New Action(AddressOf Class2.Method_Sunday))
End Sub
' a helper method to retrieve and execute the action
Private Sub DoWork(day As [Enum])
Dim actionToPerform As Action = Nothing
If WorkMethods.TryGetValue(day, actionToPerform) Then
If actionToPerform IsNot Nothing Then actionToPerform()
End If
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
DoWork(Class1.WorkDay.Wednesday)
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
DoWork(Class2.NotWorkDay.Saturday)
End Sub
End Class
Such usage gives you a lot of flexibility to configure the methods called with out needing to rewrite a Select-Case block when changes are needed. You just add/delete items in the dictionary.
来源:https://stackoverflow.com/questions/42346162/enums-and-interfaces