c# - 为什么我得到 NullReferenceException,如果有空检查
问题描述
在 WPF 和 MVVM 中使用命令绑定时出现异常。
堆栈跟踪:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object.
at xxx.TcpConnection.get_IsOpen() in C:\xxx\TcpConnection.cs:line 70
at xxx.CommunicationViewModel.<.ctor>b__5_0() in C:\xxx\CommunicationViewModel.cs:line 53
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at GalaSoft.MvvmLight.Helpers.WeakFunc`1.Execute()
at MS.Internal.Commands.CommandHelpers.CanExecuteCommandSource(ICommandSource commandSource)
at System.Windows.Controls.Primitives.ButtonBase.UpdateCanExecute()
at System.Windows.Controls.Primitives.ButtonBase.OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
at System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp, Boolean preserveCurrentValue)
at System.Windows.Data.BindingExpressionBase.Invalidate(Boolean isASubPropertyChange)
at System.Windows.Data.BindingExpression.TransferValue(Object newValue, Boolean isASubPropertyChange)
at System.Windows.Data.BindingExpression.Activate(Object item)
at System.Windows.Data.BindingExpression.AttachToContext(AttachAttempt attempt)
at System.Windows.Data.BindingExpression.MS.Internal.Data.IDataBindEngineClient.AttachToContext(Boolean lastChance)
at MS.Internal.Data.DataBindEngine.Task.Run(Boolean lastChance)
at MS.Internal.Data.DataBindEngine.Run(Object arg)
at System.Windows.ContextLayoutManager.fireLayoutUpdateEvent()
at System.Windows.ContextLayoutManager.UpdateLayout()
at System.Windows.Interop.HwndSource.SetLayoutSize()
at System.Windows.Interop.HwndSource.set_RootVisualInternal(Visual value)
at System.Windows.Window.SetRootVisual()
at System.Windows.Window.SetRootVisualAndUpdateSTC()
at System.Windows.Window.SetupInitialState(Double requestedTop, Double requestedLeft, Double requestedWidth, Double requestedHeight)
at System.Windows.Window.CreateSourceWindow(Boolean duringShow)
at System.Windows.Window.ShowHelper(Object booleanBox)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.DispatcherOperation.InvokeImpl()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
at System.Windows.Threading.DispatcherOperation.Invoke()
at System.Windows.Threading.Dispatcher.ProcessQueue()
at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
at System.Windows.Application.RunDispatcher(Object ignore)
at System.Windows.Application.RunInternal(Window window)
at xxx.App.Main()
异常可能发生在 Dispose 上,但有一个空检查。
以下是代码中有趣的部分:
CommunicationViewModel.cs:
53 this.ConnectCommand = new RelayCommand(this.Connect, () => this.CanConnect);
...
91 public bool CanConnect
92 {
93 get { return !this.Connection.IsOpen; }
94 }
this.Connection 是 TcpConnection 的一个实例
TcpConnection.cs:
63 public bool IsOpen
64 {
65 get
66 {
67 var c = this.client;
68 if (c == null)
69 {
70 return false;
71 }
72
73 return c.Connected;
74 }
75 }
我认为这是数据绑定的一种奇怪行为。有没有人遇到过类似的问题?此外,奇怪的是 CommunicationViewModel.cs 的第 93 行不包含在堆栈跟踪中。WPF 是否对代码进行了一些优化?
解决方案
推荐阅读
- ruby-on-rails - 如果块是内联或多行给出的,则 Rails 输出不同
- histogram - 为什么 distplot 中的 kde 看起来像一个正弦波?
- integration - 如何将 Zoho CRM 与 Messagebird 集成
- swift - SwiftUI - 检测 TabView 上的点击以滚动到列表顶部
- kubernetes - 卷写入权限
- javascript - 为什么对变量执行操作会影响 Vanilla JS 中的 DOM?
- java - 使用 RandomAccessFile 读取文件属性
- c++ - CMake:将可执行文件链接到多个库 (*.so)
- python - 排序算法的时间复杂度
- xcode - QtCreator 问题选项卡为空