Joe
Joe

Reputation: 11

Pass method as argument without Delegate

Does the C# compiler require a function delegate to pass a function as an argument to another function?

In Visual Basic .Net I can pass a function whose return value is of the same type as a method argument to the method itself without anything fancy. This doesn't appear possible in C# unless the method was written to accept a function delegate??

working vb:

Function DoSomething(r As DataRow())
        '...
End Function

Function CallSomething()
        Dim dt As DataTable
        DoSomething(dt.Select(""))
End Function

C# would require the calling code to assign a variable and pass that, or that the referenced function's signature included a delegate (useful to know). Subtle difference but I was expecting that a simple method call made in one language could be just as easily made in the other since they both compile to the same IL.

here's the C# equivalent I was trying to do:

string DoSomething(ref DataRow[] r)
{ ///do something }

void CallSomething()
{
    DataTable dt;
    DoSomething(ref dt.Select(""));
}

What I meant by "fancy" was the use of delegates, I've used delegates for more complex scenarios, like assigning event handlers to array elements, but I was surprised they would be required for this.

Thanks for the replies. The VB code is functioning as expected, ByRef is implicit in VB, you can't pass an object managed on the heap byval. Nonetheless, here's the simplest form I can provide in VB, if you use a simple forms project w/ a single listbox and drop this code in, should work fine:

Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
        Dim dt As New DataTable("A really great table")
        dt.Columns.Add("Column1", GetType(String))
        dt.Rows.Add("Row1") : dt.Rows.Add("Row2")
        PutRowsInListbox(dt.Select(""))
    End Sub

    Private Function PutRowsInListbox(ByRef r() As DataRow)
        For i As Integer = 0 To r.Length - 1
            Me.ListBox1.Items.Add(r(i).Item("Column1"))
        Next
    End Function
End Class

Upvotes: 0

Views: 420

Answers (1)

Zohar Peled
Zohar Peled

Reputation: 82474

  1. Your Vb.Net code is not equivalent to your c# code. If you want them to be equivalent, you need to remove the ref keyword on the c# code (or add ByRef on the VB.Net code).

  2. Both visual basic and c# allows this style of programming. Please note, however, that you are not passing a function (or method) to another method here, not in Vb nor in c# - you are simply populating the DataRow array with the results of the data table's Select method.

  3. Since you are not actually passing a method as an argument, a more readable code would be to get the results of the Select method into a variable and pass that variable into the DoSomething method - but that's more a personal preference thing.

  4. The c# code sample you have in the question will not compile.

Here's an equivalent and compilable c# version of the Vb.Net code you have now:

void DoSomething(DataRow[] r)
{ 
    //do something 
}

void CallSomething()
{
    DataTable dt = null;
    DoSomething(dt.Select(""));
}

Of course, that would throw a NullReferenceException unless you actually initialize the dt with a value instead of null.

BTW, ByRef is not implicit. passing reference types does not mean passing them by Reference. That's a common misconception.

When you pass a reference type to a method, what actually is going on is that you are passing the reference itself by value. You can test it easily yourself if you try to reassign the reference inside the method - you'll still see the old value outside the method if you didn't specify ByRef.

Upvotes: 4

Related Questions