开发者

How do you create a generic method in a class?

开发者 https://www.devze.com 2022-12-28 06:47 出处:网络
I am really trying to follow the DRY principle.I have a sub that looks like this? Private Sub DoSupplyModel

I am really trying to follow the DRY principle. I have a sub that looks like this?

Private Sub DoSupplyModel

        OutputLine("ITEM SUMMARIES")
        Dim ItemSumms As New SupplyModel.ItemSummaries(_currentSupplyModel, _excelRows)
        ItemSumms.FillRows()
        OutputLine("")

        OutputLine("NUMBERED INVENTORIES")
        Dim numInvs As New SupplyModel.NumberedInventories(_currentSupplyModel, _excelRows)
        numInvs.FillRows()
        OutputLine("")   

End Sub

I would like to collapse these into a single method using generics. For the record, ItemSummaries and NumberedInventories are both derived from the same base class DataBuilderBase.

I can't figure out the syntax that will allow me to do ItemSumms.FillRows and numInvs.FillRows in the method.

FillRows is declared as Public Overridable Sub FillRows in the base class.

Thanks in advance.

EDIT

Here is my end result

Private Sub DoSupplyModels()

    DoSupplyModelType("ITEM SUMMARIES",New DataBlocks(_currentSupplyModel,_excelRows)
    DoSupplyModelType("DATA BLOCKS",New DataBlocks(_currentSupplyModel,_excelRows)

End Sub

Private Sub DoSupplyModelType(ByVal outputDescription As String, ByVal type As DataBuilderBase)
    OutputLine(outputDescription)
    type.FillRows()
    OutputLine("")
End Sub

But to answer my own question...I could have done this...

Private Sub DoSupplyModels()

    DoSupplyModelType(Of Projections)("ITEM SUMMARIES")
    DoSupplyModelType(Of DataBlocks)("DATA BLOCKS开发者_JAVA百科")

End Sub

Private Sub DoSupplyModelType(Of T as DataBuilderBase)(ByVal outputDescription As String, ByVal type As T)
    OutputLine(outputDescription)
    Dim type as New DataBuilderBase (_currentSupplyModel,_excelRows)
    type.FillRows()
    OutputLine("")
End Sub

Is that right?

Seth


As others have pointed out, you don't need generics to do what you want, but I will answer the technical question for completeness:

Private Sub MyMethod(Of T As DataBuilderBase)(ByVal instance As T)
    instance.FillRows()
End Sub

And then call the method by doing this:

MyMethod(Of ItemSummaries)(new SupplyModel.ItemSummaries(...))


you can refactor to take advantage of the fact that the share a common base and use polymorphism: (VB a bit rusty, you should get the idea)

you could have a method:

Private Sub FillAndOutput(textToOutput as String, filler as DataBuilderBase)
    OutputLine(string)        
    filler.FillRows()
    OutputLine("")
end sub

which you could call:

Private Sub DoSupplyModel
    FillAndOutput("ITEM SUMMARIES",New SupplyModel.ItemSummaries(_currentSupplyModel, _excelRows))
    FillAndOutput("NUMBERED INVENTORIES",New SupplyModel.NumberedInventories(_currentSupplyModel, _excelRows))        

End Sub


Basically you need to specify that T will be a subclass of the base type that implements FillRows method. In C# this would look like so

private void myFunction<T>( T someList ) where T : DataBuilderBase {
    someList.FillRows();
}

Found a VB.NET example on MSDN.

EDIT and Kevin is right, this would probably be handled better with polymorphism.


In this case I don't think that refactoring to a generic function is justifiable, even at the expense of repeating yourself. You would have two options:

  1. Refactor your code so that it allows for parameterless constructors and create a function at a higher level of inheritance that allows you to specify the arguments currently being passed to the constructor.
  2. Use explicit reflection to instantiate the generic type and pass those arguments to the constructor.

Either of those options involves a non-trivial amount of work with very little gain (you're translating three lines of code into one).

However, to answer your question, VB.NET uses the of keyword to specify generic type arguments

Public Sub Foo(Of T)(argument as T)
   ...
End Sub
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号