构造函数异常后引用不为空

时间:2015-03-03 19:45:50

标签: c# wpf constructor

我有以下代码行。

Application.Current.MainWindow = new MainWindow();

将构造函数放在调试器告诉我的行上,Application.Current.MainWindow为null。 然后构造函数抛出异常。在catch块中,Application.Current.MainWindow不再为null。不应修改Application.Current.MainWindow的值,但它是。

如果我改为:

Window w = new MainWindow();

在按预期抛出异常后,w为null。

我错过了什么?

更新

只调用Window子类的构造函数会导致Application.Current.MainWindow更改为指向该实例。即使构造函数抛出异常,也会发生这种情况。这使应用程序处于不一致状态。

例如,它将让我调用Application.Current.MainWindow.Show,它会创建各种问题,因为该窗口的状态无效。

1 个答案:

答案 0 :(得分:1)

查看Application.MainWindow属性的来源

来源:http://referencesource.microsoft.com/#PresentationFramework/Framework/System/Windows/Application.cs,cf9c51e402f97b05

public Window MainWindow
{
    get
    {
        VerifyAccess();
        return _mainWindow;
    }

    set
    {
        VerifyAccess();

        //
        // Throw if an attempt is made to change RBW.
        // or we are browser hosted, main window is null, and attempt is made to change RBW.
        //
        if ( ( _mainWindow is RootBrowserWindow )
                ||
            ((BrowserCallbackServices != null ) &&
                ( _mainWindow == null ) &&
                ( !( value is RootBrowserWindow ))) )
        {
            throw new InvalidOperationException( SR.Get( SRID.CannotChangeMainWindowInBrowser ) ) ;
        }

        if (value != _mainWindow)
        {
            _mainWindow = value;
        }
    }
}

这是一个值得关注的问题。另一点是其他线程或框架本身可以在其他地方设置它。检查此评论

  

默认情况下 - MainWindow将设置为应用程序中打开的第一个窗口。   但是,可以通过编程方式设置MainWindow以指示“这是我的主窗口”。   建议编程风格在代码而不是Windows [0]中引用MainWindow。

运行时无法在构造函数完成之前设置对已分配内存的引用。它可以作为优化来完成,但只能使用特定于框架的类,例如System.String

编辑:查看Window.Initialize方法

private void Initialize()
{
    // AVTempUIPermission avtUIPermission = new AVTempUIPermission(AVTUIPermissionNewWindow.LaunchNewWindows);
    // CASRemoval:avtUIPermission.Demand();

    //  this makes MeasureCore / ArrangeCore to defer to direct MeasureOverride and ArrangeOverride calls
    //  without reading Width / Height properties and modifying input constraint size parameter...
    BypassLayoutPolicies = true;

    // check if within an app && on the same thread
    if (IsInsideApp == true)
    {
        if (Application.Current.Dispatcher.Thread == Dispatcher.CurrentDispatcher.Thread)
        {
            // add to window collection
            // use internal version since we want to update the underlying collection
            App.WindowsInternal.Add(this);
            if (App.MainWindow == null)
            {
                App.MainWindow = this;
            }
        }
        else
        {
            App.NonAppWindowsInternal.Add(this);
        }
    }
}

特别是在行:

App.WindowsInternal.Add(this);
if (App.MainWindow == null)
{
    App.MainWindow = this;
}

这是设置Window属性的地方。而且因为MainWindow来自Window,所以这会在您抛出异常之前发生。