通过 VB.NET 和 C# 中的 Ref 参数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16854616/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 13:48:46  来源:igfitidea点击:

By Ref parameters in VB.NET and C#

c#vb.netpass-by-referencebyref

提问by user2439901

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#

我有与 byRef 传递参数相关的问题,我有基于 VB.NET 的类库,其中一些函数是用 byref 参数类型定义的。这些参数是父类对象,当我尝试调用此函数并在 byref 参数中传递子类对象时,它在 VB.NET 中工作,但我无法在 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

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

// 这里我可以调用 Show 方法并将子对象传递给 ByRef 类型参数,它可以工作

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#

// 但是当我在 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

我收到错误,说 Son 不能转换为父亲,我已经在 VB 中测试过它的工作原理,但是我怎样才能让它在 C# 中工作?因为我有 dll 格式的类库

Thanks in advance

提前致谢

回答by Hans Passant

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 rewritesyour code and creates a variable of the required type. Roughly like this, expressed in C#:

C# 对此很严格,通过引用传递的变量必须与方法参数类型完全匹配。VB.NET 对此很宽容,它的编译器会重写您的代码并创建所需类型的变量。大致是这样的,用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 newobject 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.

这很好,但并非没有问题。失败模式是 Show() 方法将对象分配给错误类型的参数。因为参数类型是Father,所以允许创建一个Father 对象。然而,这将使上述代码段中的第 4 条语句失败,不能将父转换为子。这不是那么漂亮,异常会在错误的语句中引发,真正的问题出在 Show() 方法中。您可以暂时忽略这一点,这至少是因为转换实际上在您的 VB.NET 源代码中不可见。哎哟。C# 强制您显式编写上述代码段,这解决了您的问题。

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 notdeclare 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.

此时您应该惊呼“但是等等,Show() 方法实际上并没有创建一个新对象!” 这是很好的启示,你会发现这段代码的真正问题,Show()方法应该声明参数为ByRef。只有在方法重新分配参数并且需要将更改传播回调用方时才应使用它。最好完全避免,对象应该由方法通过其返回值返回。VB.NET 中的函数而不是 Sub。

回答by Medinoc

ByRefallows the function to modify the managed pointer and make it point to something other than a Son, therefore C# won't allow you to pass a managed pointer to Sondirectly. However, you can do this:

ByRef允许函数修改托管指针并使其指向 a 以外的其他内容Son,因此 C# 不允许您Son直接将托管指针传递给。但是,您可以这样做:

Son s = new Son();
Father f = s;
p.Show(ref f);
s = (Son)f; //Success if f still points to a Son, InvalidCastException  otherwise.

However, if your method Showreally does not modify the managed pointer, then there is no reason for taking it ByRef: Just pass it ByValand you'll still be able to modify the object itself.

但是,如果您的方法Show确实没有修改托管指针,则没有理由接受它ByRef:只需传递它ByVal,您仍然可以修改对象本身。