简体   繁体   English

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

[英]Reference Not Null After Constructor Exception

I have the following line of code. 我有以下代码行。

Application.Current.MainWindow = new MainWindow();

Placing the constructor on the line the debugger tells me Application.Current.MainWindow is null. 将构造函数放在调试器的行上,告诉我Application.Current.MainWindow为null。 The constructor then throws an exception. 然后,构造函数将引发异常。 In the catch block Application.Current.MainWindow is no longer null. 在catch块中,Application.Current.MainWindow不再为null。 The value of Application.Current.MainWindow should not be modified, but it is. Application.Current.MainWindow的值不应修改,但可以修改。

If I instead do: 如果我改为:

Window w = new MainWindow();

w is null after the exception is thrown as expected. 在按预期引发异常之后,w为null。

What am I missing? 我想念什么?

Update 更新

Just calling the constructor for a class that subclasses Window causes Application.Current.MainWindow to change to point to that instance. 只是调用子类Window的类的构造函数,就会导致Application.Current.MainWindow更改为指向该实例。 This occurs even if the constructor throws an exception. 即使构造函数抛出异常,也会发生这种情况。 This leaves the application in an inconsistent state. 这会使应用程序处于不一致状态。

For example, it will then let me call Application.Current.MainWindow.Show, which creates all sorts of issues, because the state of that Window is invalid. 例如,然后它将让我调用Application.Current.MainWindow.Show,它将创建各种问题,因为该Window的状态无效。

Check out the source of the Application.MainWindow property 签出Application.MainWindow属性的源代码

Source: http://referencesource.microsoft.com/#PresentationFramework/Framework/System/Windows/Application.cs,cf9c51e402f97b05 来源: 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;
        }
    }
}

This is one point of concern. 这是一个值得关注的问题。 The other point is that other thread or the framework itself can set it in some other place. 另一点是其他线程或框架本身可以将其设置在其他位置。 Check this comment 检查此评论

By default - MainWindow will be set to the first window opened in the application. 默认情况下-MainWindow将设置为在应用程序中打开的第一个窗口。 However the MainWindow may be set programmatically to indicate "this is my main window". 但是,可以通过编程方式设置MainWindow以指示“这是我的主窗口”。 It is a recommended programming style to refer to MainWindow in code instead of Windows[0]. 建议使用一种编程风格,而不是Windows [0],而是用代码引用MainWindow。

There is no way that runtime can set a reference to a allocated memory before constructor finished. 在构造函数完成之前,运行时无法设置对已分配内存的引用。 It maybe done as an optimization, but only with a classes that are specific to framework, like System.String . 可能是作为优化来完成的,但只能使用特定于框架的类,例如System.String

Edit: Look at Window.Initialize method 编辑:看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);
        }
    }
}

Specifically at lines: 特别是在行:

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

This is where Window property gets set. 这是设置Window属性的地方。 And because your MainWindow is derived from Window , this happens before you get to throwing your exception. 而且由于MainWindow派生自Window ,所以在抛出异常之前就发生了这种情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 默认构造函数之后的空引用异常 - Null reference Exception after default constructor 构造函数上的Null引用异常 - Null Reference Exception On Constructor 为什么在构造函数中抛出异常导致空引用? - Why throwing exception in constructor results in a null reference? 初始化数组后获取空引用异常 - get null reference exception after initialize the array 在一定的秒数后空引用异常 - Null reference exception after a certain amount of seconds Xamarin OpenGL GLSurfaceView构造函数引发空引用异常 - Xamarin OpenGL GLSurfaceView constructor throws null reference exception WPF-Linq移至构造函数会导致null引用异常,怎么来? - WPF - Linq moved to constructor is causing null reference exception, how come? ServiceStack IAppSettings 未就绪,如果在构造函数中使用,将导致 NULL 引用异常 - ServiceStack IAppSettings was not ready and would result NULL reference exception if used in constructor json数据反序列化后给出空引用异常 - json data gives null reference exception after deserialization Devexpress - 插入先前删除的系列后 Null 引用异常 - Devexpress - Null reference exception after inserting previously deleted series
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM