简体   繁体   中英

How do you create a generic method in a class?

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")

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM