通过 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
By Ref parameters in VB.NET and C#
提问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,您仍然可以修改对象本身。

