By Ref parameters in VB.NET and C#

user2439901 picture user2439901 · May 31, 2013 · Viewed 8.4k times · Source

I have question related passing parameters byRef, I have VB.NET based class library in which some functions are defined with byref argument types. These parameters are parent class objects and when I tried to call this function and pass child class object in byref argument it works in VB.NET but I am unable to do same thing in C#

following is test code i am trying

Public Class Father

        Private _Cast As String
        Public Property Cast() As String
            Get
                Return _Cast
            End Get
            Set(ByVal value As String)
                _Cast = value
            End Set
        End Property

    End Class


 Public Class Son
        Inherits Father

        Private _MyName As String
        Public Property Myname() As String
            Get
                Return _MyName
            End Get
            Set(ByVal value As String)
                _MyName = value
            End Set
        End Property


    End Class

Implementation class in VB

Public Class Parent

        Public Function Show(ByRef value As Father) As Boolean
            Dim test As String = value.Cast
            Return True
        End Function

// Herer I can call Show method and pass child object to ByRef type argument and it works

Public Function Show2() As Boolean

            Dim s As New Son
            Dim result As Boolean = Show(s)

            Return True
        End Function

    End Class

// But when i try same thing in c#

Parent p = new Parent();
            Son s = new Son();
            Father f = new Father();

            p.Show(ref s);

I get error that Son cannot convert to father , I already test it works in VB but how can I make it work in c#? as I have class library in dll format

Thanks in advance

Answer

Hans Passant picture Hans Passant · May 31, 2013

C# is strict about this, a variable that's passed by reference must be an exact match with the method argument type. VB.NET is forgiving about that, its compiler rewrites your code and creates a variable of the required type. Roughly like this, expressed in C#:

    Son s = new Son();
    Father $temp = (Father)s;
    p.Show(ref $temp);
    s = (Son)$temp;

Which is nice, but not without problems. The failure mode is when the Show() method assigns a new object to its argument of the wrong type. It is allowed to create a Father object since the argument type is Father. That however will make the 4th statement in the above snippet fail, can't cast Father to Son. That's not so pretty, the exception will be raised at the wrong statement, the true problem is located in the Show() method. You can scratch your head over that for a while, not in the least because the cast is not actually visible in your VB.NET source code. Ouch. C# forces you to write the above snippet explicitly, which solves your problem.

At this point you should exclaim "But wait, the Show() method doesn't actually create a new object!" That's good insight and you'll have found the true problem in this code, the Show() method should not declare the argument ByRef. It should only be used when a method reassigns the argument and that change needs to be propagated back to the caller. Best avoided entirely, an object should be returned by a method by its return value. Function in VB.NET instead of Sub.