【問題解決】無法創建新的堆棧防護頁面


【問題發現】

      項目中需要幾個自定義的控件,菜鳥D定義了一個接口,打算使用多態來統一調用。在完成兩個自定義控件后,項目都能正常運行。但是在第三個控件使用的時候就出了問題:將控件拖到界面上以后,不能拖動改變控件的寬度,一拖動就會出現“無法創建新的堆棧防護頁面”的提示,然后vs直接崩潰。后來經過多次嘗試,發現可以輸入改變控件的寬度,但是依然會有崩潰發生。

【問題解決】

      菜鳥D在網上搜索相關的解決辦法,但是幾乎所有的回答都在說是遞歸調用導致溢出。菜鳥D發現自己的程序中有遞歸的調用,但是前兩個控件也是調用的這一個遞歸方法,如果是方法本身的問題,那兩種控件也一定會出錯,但事實是那兩種控件可以正常使用的。所以問題一定就在新的自定義控件上。

      由於崩潰是在改變控件的寬度后發生的,必須看看寬度的屬性,以下是部分代碼:

public  int Width {
            get { return this.Width; }
            set { Width = value;
//此處自定義控件內部的控件的location的設置,如:lable1.location=new Piont(); //為了實現一個聯動的效果
}
}

      這時菜鳥D注意到代碼左側的提示:

      Recursive call 不就是遞歸么!!!原來如此,是這里的遞歸導致了崩潰。刪掉這段代碼后,控件隨意拖拉也再沒出現那樣的錯誤了。問題到此已經得到了解決。

【問題的分析】

      菜鳥D不明白為什么這么寫會造成遞歸,於是開始接下來的查找。

     在get里面的Width上用F12,發現光標只是向上跳了一行,這個好像不對,感覺有點怪。隨即想到既然這是自定義控件,繼承Control控件類,控件類里面會不會做了相應的封裝。於是,轉到定義,以下代碼展示繼承關系:

public partial class ExControlBox : UserControl, IControlCommonable

public class UserControl : ContainerControl public class ContainerControl : ScrollableControl, IContainerControl

public class ScrollableControl : Control, IComponent, IDisposable

public class Control : Component, IDropTarget, ISynchronizeInvoke, IWin32Window, IBindableComponent, IComponent, IDisposable
// Control基類中的兩個屬性
public int Width { get; set; }
public virtual string Text { get; set; }

      果然在Control基類里找到Width屬性,當看到Text屬性時想起曾經使用過override重寫過Text屬性,那是否可以換一種寫法“重寫”Width屬性?當然可以——new。New 作為運算符用於創建對象和調用構造函數,作為修飾符用於隱藏基類中被繼承的成員(出自msdn)。

於是改造了原來的Width屬性的寫法,也能成功運行沒有發生崩潰。代碼如下:

new public int Width
        {
            get { return base.Width; }
            set
            {
                base.Width = value;
                //此處自定義控件內部的控件的location的設置,如:lable1.location=new Piont(); //為了實現一個聯動的效果
            }
        }

總結

1.在定義屬性時,應注意是否該屬性已經存在於基類,如果存在,就需要判斷是需要重寫該屬性,還是隱藏該屬性。

2.遞歸的調用一定要謹慎,否則可能造成溢出,導致崩潰。 

菜鳥D希望這篇文章對您有所幫助。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM