gpt4 book ai didi

vb.net - VB 传递参数值 ByRef 在方法退出之前不会改变值?

转载 作者:行者123 更新时间:2023-12-03 19:58:18 26 4
gpt4 key购买 nike

我在 .Net Entity Framework 中有一个类,它实现了 INotifyPropertyChanged。我发现了一个有趣的问题,我的属性更改 setter 会触发通知事件,但更改的值在 setter 退出之前不可见。

我实现了以下内容来测试属性值是否已更改,设置新值,然后将更改通知相关方:

Public Event PropertyChanged(sender As Object, 
e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged

'' This method is called by the Set accessor of each property.
Private Sub NotifyPropertyChanged(PropertyName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(PropertyName))
End Sub

''' <summary>
''' Sets the specified property to a value and raises an event if the property has changed.
''' </summary>
''' <typeparam name="T">Type of the destination field</typeparam>
''' <param name="field">Destination Field to check/update</param>
''' <param name="value">Field is to be set to this value, if it has not changed.</param>
''' <param name="PropertyName">Optional property name - filled in by compiler if left blank.</param>
''' <remarks></remarks>
Protected Function SetProperty(Of T)(ByRef field As T, value As T, _
PropertyName As String, _
Optional SupressEvent As Boolean = False) As Boolean
If Not EqualityComparer(Of T).Default.Equals(field, value) Then
field = value
If Not SupressEvent Then NotifyPropertyChanged(PropertyName)
Return True
End If
Return False
End Function

属性本身调用 SetProperty 如下:
Public Property AccruedShares As Decimal
Get
Return Me.AccruedSharesValue
End Get
Set(value As Decimal)
SetProperty(Of Decimal)(Me.AccruedSharesValue, value, "AccruedShares", Loading)
End Set
End Property

问题是设置一个 10 的值并调用 SetProperty 会导致对许多其他方法的通知,但是在 SetProperty 退出并返回到集合之前,属性的值不会更改。例如在 AccruedSharesValue 上设置监视显示值为 0。当事件触发时,所有其他方法看到的值为 0,并且在代码退出 SetProperty 方法之前不会更改为 10。这与我如何看待通过 ref 工作传递值的方式完全相反。 ByRef 应该立即更改传递变量的值,而不是在方法退出后。

有没有人知道为什么会这样?

最佳答案

我拿了一小段代码:

    Public Property Population As Integer
Get
Return Me.PopulationValue
End Get
Set(value As Integer)
SetProperty(Of Integer)(Me.PopulationValue, value, "Population")
End Set
End Property

然后检查了反汇编列表:
.method public specialname instance void 
set_Population(int32 'value') cil managed
{
// Code size 31 (0x1f)
.maxstack 5
.locals init ([0] int32 VB$t_i4$S0)
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: callvirt instance int32 Armada.DataModels.City::get_PopulationValue()
IL_0007: stloc.0
IL_0008: ldloca.s VB$t_i4$S0
IL_000a: ldarg.1
IL_000b: ldstr "Population"
IL_0010: ldc.i4.0
IL_0011: callvirt instance bool Armada.DataModels.City::SetProperty<int32>(!!0&,
!!0,
string,
bool)
IL_0016: pop
IL_0017: ldarg.0
IL_0018: ldloc.0
IL_0019: callvirt instance void Armada.DataModels.City::set_PopulationValue(int32)
IL_001e: ret
} // end of method City::set_Population

显然,从上面的代码中可以看出,在调用从 IL_0019 行的 SetProperty 返回后,编译器从堆栈中弹出一个返回值,然后将其分配给 my 值。同样,这似乎只发生在通用方法中。我还没有用普通方法看到这种行为。

我真的认为这应该标记为 Microsoft 错误?

关于vb.net - VB 传递参数值 ByRef 在方法退出之前不会改变值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28491335/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com