简体   繁体   中英

Convert VB.NET delegate to C#

I would like to convert this single line of code from VB.NET to C#:

Private callback As clsCompareLibs.ResultCallback = AddressOf zipCallback

How can I convert the above code to C#? The application works if I add the following lines of code, but without the progressbar and the function zipCallback is called, but never enters the else part:

    public delegate void zipCallbackHendler(ref CompareLibs.ZipData _zipData);
    zipCallbackHendler ziphandler; 
    CompareLibs.ResultCallback callback/*=ziphandler*/;

The code for zipCallback:

Private Sub zipCallback(ByRef zipData As clsCompareLibs.ZipData)

    Static lastName As String

    If Me.InvokeRequired Then
        Me.Invoke(callback, zipData)
    Else

        With zipData
            If .fileList IsNot Nothing AndAlso .fileList.Count > 0 Then
                ' We've received a list of files. Add them to the listbox.
                Dim names As New List(Of String)
                currentEntries.Clear()

                For Each entry As clsCompareLibs.ShortEntry In .fileList
                    names.Add(entry.name)
                    currentEntries.Add(entry)
                Next

                Me.lbFileList.Items.AddRange(names.ToArray())

                Me.lblFileName.Text = "Complete."

                Try
                    zipLib.Close()
                Catch ex As Exception
                End Try

                me.Cursor = System.Windows.Forms.Cursors.Default
            Else
                ' We're updating the UI with progress data here.

                ' Have we moved on to a new file?
                If lastName <> zipData.currentFileName Then
                    ' If so, set the progress bar to 0.
                    pbCurrentFile.Value = 0 
                    lastName = zipData.currentFileName
                End If

                lblFileName.Text = .operationTitle
                If .currentFileName <> "" Then lblFileName.Text += ": ...\" & Path.GetFileName(.currentFileName)
                If .currentFileBytesCopied > 0 AndAlso .totalBytes > 0 Then
                    pbCurrentFile.Value = CInt((.currentFileBytesCopied / .currentFileLength) * 100)
                    pbTotalBytes.Value = CInt((.totalBytesCopied / .totalBytes) * 100)

                    pbCurrentFile.Refresh()
                    pbTotalBytes.Refresh()
                End If

                If .complete Then
                    zipLib.Close()
                    If .cancel Then 
                        lblFileName.Text = "Canceled."
                        pbCurrentFile.Value     = 0
                        pbTotalBytes.Value      = 0
                    Else
                        endTime = Now
                        If endTime.Subtract(startTime).TotalSeconds > 60 then
                            lblFileName.Text = "Complete. This operation took " & _
                                endTime.Subtract(startTime).Minutes.ToString() & _
                                " minutes, and " & endTime.Subtract(startTime).Seconds.ToString() & " seconds."
                        Else
                            lblFileName.Text = "Complete. This operation took " & _
                                endTime.Subtract(startTime).TotalSeconds.ToString("N1") & _
                                " seconds."
                        End If
                    End If

                    tsbZipFiles.Visible         = True
                    tsbZipFiles.Enabled         = True
                    tsbListZipEntries.Visible   = True
                    tsbCancel.Visible           = False
                    me.Cursor = System.Windows.Forms.Cursors.Default
                End If

                If .errorMessage <> "" Then 
                    MsgBox("" & .errorMessage, MsgBoxStyle.Critical, "Zip Example App")
                    me.Cursor = System.Windows.Forms.Cursors.Default
                End If
            End If
        End With
    End If

End Sub

In main:

            zipLib = New clsCompareLibs(zipPath, clsCompareLibs.ZipAccessFlags.Create, 1024 * 1024, _
            cbDotNetZip.Checked, CInt(nudCompression.Value), cbZip64.Checked, tbPassword.Text, 100, AddressOf zipCallback)

ResultCallback:

Public Delegate Sub ResultCallback(ByRef _zipData As ZipData)

The zipCallback method is a member of a class. Since the method might use other members of that class type, you also need an instance of the class to use with the delegate, so the code knows what instance to look at if another member is referenced.

To help understand, think about this code:

Public Class Foo
    Public A As String

    Public Sub Bar(Baz As String)
         A = A & Baz
    End Sub
End Class

Dim x As New Foo With {.A = "x"}
Dim y As New Foo With {.A = "y"}

Now imagine trying to use Foo.Bar() as your delegate callback. You'd see different results depending on whether you use the x instance or the y instance. Which one do we want? Or maybe we meant a different instance completely. The point is you need to know.

Instead of this:

AddressOf Bar

you need this:

AddressOf x.Bar

or

AddressOf y.Bar

The original project manages this with an implied Me instance reference ( this in C#). It works because the zipCallback() and the code using it with AddressOf are both in the same class , and so we have an implied instance.

It's not clear this remains true with the code in the question. If the zipCallback() method has moved to a different class from the Main class in the project, you'll need to know which instance of the class you're using as part of the AddressOf statement.

For completeness, the other option is VB code using a Module instead of a Class . In that case, the equivalent C# should have a static class and the method should also be marked static ( Shared in VB parlance).

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