我一直在使用WPF和MVVM开发一个项目。在我的项目中的某个部分,我使用了以下代码来关闭窗口。代码可以正常运行,但是我还不理解其中的逻辑。我的代码如下:
App.Current.Windows.Cast<Window>()
.Where(win => win is DisplayView).FirstOrDefault()
.Close();
为什么需要使用FirstOrDefault()方法?
我一直在使用WPF和MVVM开发一个项目。在我的项目中的某个部分,我使用了以下代码来关闭窗口。代码可以正常运行,但是我还不理解其中的逻辑。我的代码如下:
App.Current.Windows.Cast<Window>()
.Where(win => win is DisplayView).FirstOrDefault()
.Close();
它只是使用了一些Linq IEnumerable<T>
扩展,以从与给定类型匹配的集合中获取第一个项目,然后在该实例上调用 Close
。 实际上,这是不必要的冗长,因为这个:
App.Current.Windows.Cast<Window>()
.Where(win => win is DisplayView)
这基本上相当于:
App.Current.Windows.OfType<DisplayView>()
FirstOrDefault()
再调用 "Close" 有点儿傻。FirstOrDefault 类似于 First
,不同之处在于如果没有元素,它会返回 null 而不是抛出异常 -- 但在这种情况下,你仍然会因为调用 null 对象的 "Close" 方法而抛出异常。App.Current.Windows.OfType<DisplayView>().First().Close();
如果您想要验证确实存在一个DisplayView实例,并且在这种情况下防止异常发生,那么可以使用以下代码:
var displayViews = App.Current.Windows.OfType<DisplayView>();
if (displayViews.Any())
displayViews.First().Close();
让我们来分解一下:
App.Current
:获取正在运行的 WPF 应用程序(我认为应该是 Application.Current
).Windows.Cast<Window>()
:获取窗口列表,但由于这是一个未经类型化的集合,因此需要将其强制转换为强类型以使用所有LINQ运算符.Where(win => win is DisplayView)
:LINQ 运算符,用于过滤窗口列表并仅保留那些类型为DisplayView
的窗口.FirstOrDefault()
:获取此集合的第一个元素或null
(如果没有找到).Close()
:关闭我们获取的窗口,这很危险,因为如果没有找到窗口,它会引发NullReferenceException
以下是更安全的方法:
DisplayView view = App.Current.Windows.Cast<Window>()
.Where(win => win is DisplayView)
.FirstOrDefault();
if (view != null)
{
view.Close();
}