【問題發現】ide
項目中須要幾個自定義的控件,菜鳥D定義了一個接口,打算使用多態來統一調用。在完成兩個自定義控件後,項目都能正常運行。可是在第三個控件使用的時候就出了問題:將控件拖到界面上之後,不能拖動改變控件的寬度,一拖動就會出現「沒法建立新的堆棧防禦頁面」的提示,而後vs直接崩潰。後來通過屢次嘗試,發現能夠輸入改變控件的寬度,可是依然會有崩潰發生。函數
【問題解決】this
菜鳥D在網上搜索相關的解決辦法,可是幾乎全部的回答都在說是遞歸調用致使溢出。菜鳥D發現本身的程序中有遞歸的調用,可是前兩個控件也是調用的這一個遞歸方法,若是是方法自己的問題,那兩種控件也必定會出錯,但事實是那兩種控件能夠正常使用的。因此問題必定就在新的自定義控件上。spa
因爲崩潰是在改變控件的寬度後發生的,必須看看寬度的屬性,如下是部分代碼:code
public int Width { get { return this.Width; } set { Width = value;
//此處自定義控件內部的控件的location的設置,如:lable1.location=new Piont(); //爲了實現一個聯動的效果
} }
這時菜鳥D注意到代碼左側的提示:對象
Recursive call 不就是遞歸麼!!!原來如此,是這裏的遞歸致使了崩潰。刪掉這段代碼後,控件隨意拖拉也再沒出現那樣的錯誤了。問題到此已經獲得瞭解決。blog
【問題的分析】繼承
菜鳥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但願這篇文章對您有所幫助。