David
David

Reputation: 2324

Return value gets assigned but always returns as 0

I'm trying to calculate the total count and value of orders for a customer, using the code below.

    Dim iOrderCount As Integer
    Dim iLineCount As Integer
    Dim cTotalGoods As Decimal
    Dim cTotalVat As Decimal
    Dim cTotalDelivery As Decimal

    Using manOrders As New CManOrders(m_dbSql)
manOrders.GetOrdersInProgress(sAccountCode, iOrderCount, iLineCount, cTotalGoods, cTotalVat, cTotalDelivery)

When I assign values to these variables in the GetOrdersInProgress subroutine, the values are being assigned correctly, which I can see when I step through the code.

Public Sub GetOrdersInProgress(sAccountCode As String, ByRef RET_orderCount As Integer, ByRef RET_lineCount As Integer,
                               ByRef RET_totalGoods As Decimal, ByRef RET_totalVat As Decimal, RET_totalDelivery As Decimal)

    ...

    For Each dr As DataRow In m_dbSql.getDataTable(sql).Rows
        RET_orderCount = dbToInt(dr(ORDER_COUNT))
        RET_lineCount = dbToInt(dr(LINE_COUNT))
        RET_totalGoods = dbToDecimal(dr(TOTAL_GOODS))
        RET_totalVat = dbToDecimal(dr(TOTAL_VAT))
        RET_totalDelivery = dbToDecimal(dr(2))

        Return
    Next

However, once I step through and move back into where the GetOrdersInProgress subroutine is called from, all of the values in the variables are returned correctly, except for RET_totalDelivery - the new one I've added to another developer's project. The value in the RET_totalDelivery variable in the Public Sub GetOrdersInProgress... line is correct and it's correct after the assignment, but when it reaches Return and the variables are then used in the parent subroutine, for some reason they're all correct except for the new one I've added, RET_totalDelivery. I'd understand if the value wasn't being assigned correctly, however it is.

Why would it be returning 0 all the time?

Upvotes: 1

Views: 259

Answers (2)

Han
Han

Reputation: 3072

I prefer to write the method as a function. Write a class to hold all the return values. Then change the method into a function with just input parameters and return the values you fetch from sql.

Sub Main
    Dim bl = New OrdersInProgressBusinessLogic()
    Dim ordersInProgress = bl.GetOrdersInProgress("some account code")
End Sub

Public Class OrdersInProgress
    Public Property OrderCount As Integer
    Public Property LineCount As Integer
    Public Property TotalGoods As Decimal
    Public Property TotalVat As Decimal
    Public Property TotalDelivery As Decimal
End Class

Public Class OrdersInProgressBusinessLogic

    Public Function GetOrdersInProgress(sAccountCode As String) As OrdersInProgress
        Dim ordersInProgress = New OrdersInProgress()

        ' some code here to fetch data from sql

        For Each dr As DataRow In m_dbSql.getDataTable(sql).Rows
            With ordersInProgress
                .OrderCount = dbToInt(dr(ORDER_COUNT))
                .LineCount = dbToInt(dr(LINE_COUNT))
                .TotalGoods = dbToDecimal(dr(TOTAL_GOODS))
                .TotalVat = dbToDecimal(dr(TOTAL_VAT))
                .TotalDelivery = dbToDecimal(dr(2))
            End With
        Next

        Return ordersInProgress
    End Function

    ' some other functions/subs for OrdersInProgress class

End Class

Upvotes: 1

Spevacus
Spevacus

Reputation: 614

By default, arguments passed to vb.net methods are passed by value, or ByVal. You did not specify ByRef in your RET_totalDelivery argument in GetOrdersInProgress.

Changes made to arguments passed by value are not retained when the method ends.

Your Sub should now be...

Public Sub GetOrdersInProgress(sAccountCode As String, ByRef RET_orderCount As Integer, ByRef RET_lineCount As Integer, ByRef RET_totalGoods As Decimal, ByRef RET_totalVat As Decimal, ByRef RET_totalDelivery As Decimal)

Upvotes: 5

Related Questions