拳击在C#和VB中表现不同

PEt*_*ter 8 .net c# vb.net

我正在尝试将结构传递给子/ void以用数据填充它.在C#中,这样可以正常工作

[TestFixture]
public class Boxing
{
    [Test]
    public void BoxingValue()
    {
       var res = (object)new Test();
       SomeVoid(res);         
        Assert.AreEqual(2, ((Test)res).Id);
    }

    public static void SomeVoid(object b)
    {
        var f = b.GetType().GetField("Id");
        f.SetValue(b, 2);
    }

    public struct Test
    {
        public int Id;
    }
}
Run Code Online (Sandbox Code Playgroud)

此代码在vb thoug中通过C#中的测试

<Test> Public Sub StructTest()
  Dim s As Object
    s = CObj(New Test)
    A(s)
    Assert.AreEqual(2, CType(s, Test).Id)
End Sub

Public Sub A(val As Object)
    Dim f = val.GetType().GetField("Id")
    f.SetValue(val, 2)
End Sub

Public Structure Test
    Public Id As Integer
End Structure
Run Code Online (Sandbox Code Playgroud)

有没有人对此有解释..

奇怪?

D S*_*ley 7

我相信这是一个已知的限制,SetValue在传递结构时使用VB(即使变量本身被声明为Object).如果你看的内容valA前和呼叫后SetValue,你会看到,它不改变结构的价值.我看到的解释是VB在内部再次封装基础值(通过调用GetObjectValue),创建副本,并更改副本的值.

我看到的一个解决方法是将值转换为a ValueType并对其进行调用SetValue(您还需要将参数更改为显式ByRef:

Public Sub A(ByRef val As Object)
    Dim f = val.GetType().GetField("Id")
    If val.GetType.IsValueType Then
        Dim vt As ValueType = val
        f.SetValue(vt, 2)
        val = vt
    Else
        f.SetValue(val, 2)
    End If    
End Sub
Run Code Online (Sandbox Code Playgroud)

当然,这种复杂性只是强调了应该不惜一切代价避免可变结构的原则.