6

我有与传递参数 byRef 相关的问题,我有基于 VB.NET 的类库,其中一些函数是用 byref 参数类型定义的。这些参数是父类对象,当我尝试调用此函数并在 byref 参数中传递子类对象时,它在 VB.NET 中工作,但我无法在 C# 中做同样的事情

以下是我正在尝试的测试代码

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

VB中的实现类

Public Class Parent

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

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

Public Function Show2() As Boolean

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

            Return True
        End Function

    End Class

// 但是当我在 c# 中尝试同样的事情时

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

            p.Show(ref s);

我收到 Son 无法转换为父亲的错误,我已经测试过它可以在 VB 中工作,但我怎样才能让它在 c# 中工作?因为我有 dll 格式的类库

提前致谢

4

2 回答 2

10

C# 对此非常严格,通过引用传递的变量必须与方法参数类型完全匹配。VB.NET 对此很宽容,它的编译器会重写您的代码并创建所需类型的变量。大致像这样,用 C# 表示:

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

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

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

于 2013-05-31T10:37:55.230 回答
4

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.

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

于 2013-05-31T10:11:10.150 回答