[英]Why does my program's control flow seem to jump around when stepping through a factorial method?
[英]When stepping through my program the ToString() method is being called for no reason
這是一個奇怪的問題,我旁邊的高級程序員也感到困惑。 完整的問題是,以某種方式調用了我的ToString()
方法,我不知道或不知道這是我的代碼如何
static void Main(string[] args)
{
Console.Out.WriteLine("Blank Constructor");
Form form = new Form(); <-- ToString() gets called on this line.
form.ToString();
Console.Read();
}
public Form()
{
FormName = "";
FormImageLocation = "";
FormDescription = "";
FormID = 0;
CreatedDate = DateTime.Now;
LastUpdate = DateTime.Now;
Fields = new List<Field>();
Packets = new List<Packet>(); <-- This line in the constructor
}
public override string ToString()
{
string returnString;
returnString = " Form Name: " + FormName + " Form Image Location: " + FormImageLocation + "Form Description: " + FormDescription + " FormID: " + FormID + " Created Date: " + CreatedDate + " LastUpdate: " + LastUpdate ;
if (fields.Count != 0)
{
foreach (var field in fields)
{
returnString += field.ToString();
}
}
else
{
returnString += "!!! This Form has no Fields !!!";
}
if (Packets.Count != 0)
{
foreach (var packet in Packets)
{
returnString += packet.ToString();
}
}
else
{
returnString += " !!! This Form does not belong to any Packets !!!";
}
Console.Out.WriteLine(returnString);
return returnString;
}
public Packet(string packet_name, List<Form> list_of_forms)
{
PacketName = packet_name;
forms = list_of_forms;
}
僅當我逐步執行程序時,才會出現ToString()
打印的這種看似隨機的重復。 它會在我上面指定的行上打印,並且在構造函數退出並在我逐步遍歷ToString()
方法本身時瘋狂打印時也會打印。 我在ToString()
放置了一個斷點,但只有在合法調用ToString()
時,它才會在斷點處停止,因此請注意,當我逐步執行並進行此隨機打印時,它不會在斷點內停止ToString()
。 我經過並刪除了對ToString()
所有調用,當我注釋了returnString
變量並僅返回“她在那里”時,它仍然被隨機調用,問題消失了,但這無濟於事。 如果我只運行沒有斷點的程序,則不會發生此問題。 你們中的有些人可能會說,如果在運行時可以正常運行,沒關系,但是這讓我非常警惕,如果我遇到了一個代碼問題,而我會嘗試逐步檢查代碼以發現問題,那么我會得到不同的結果並妨礙調試。 我嘗試涵蓋整個問題以及我嘗試過的內容並提供所有需要的代碼,如果我不清楚讓我知道的事情,我將嘗試再次進行解釋。 最后,我在Windows 7 64位計算機上,並且使用的是Visual Studio C#2010 Express。
您可能在表單上有一塊手表,或者以其他方式在調試器中顯示它的值(通過“ locals”窗口,堆棧跟蹤等)。 調試器使用ToString
來顯示對象。 如果這是程序中的問題,則應該重新設計ToString
這樣調用它就不會有問題,或者只是避免使用調試器。
通常要避免使用非常“昂貴”的ToString
是一種需要警惕的情況。 有時可能會有例外,但確實如此,但呼叫者通常希望它是廉價的操作。 考慮是否有一些其他的方法/屬性來代表顯示字符串,而該方法/屬性涉及更多的內容,而留下一個更簡單/更便宜的ToString
實現是否合適。
如果您觀看調試器,或者只是將鼠標懸停在對象上,調試器可能會調用ToString。 通常,將ToString中的副作用保持在最低限度是一個好主意。 即ToString不應引起任何狀態更改。
如果您觀看屬性並且get方法具有副作用,則會發生類似的問題。
另一個問題是使用LINQ時,因為調試器可能會評估從LINQ表達式返回的IEnumerable,這可能會引起各種副作用。 使用LINQ可能會變得更加棘手。 如果您有一些代碼實際上依賴於重新評估LINQ表達式的代碼(例如,某些代碼輪詢某些LINQ表達式,直到某些條件成立),那么在調試時您可能會遇到一些麻煩,因為調試器可能會緩存該表達式而不會重新-如您所願進行評估。
另一個類似的調試噩夢:調試焦點事件。 這很困難,因為激活調試器將失去焦點並產生副作用。 有時,良好的老式打印語句是最佳選擇。
我認為為了在Form()中顯示那些DateTime,當您嘗試實例化新的Form()時,調試器將在它們上調用ToString()...如@Servy所述
由於在Form()類中使用的不僅僅是字符串,因此必須調用ToString()以在您設置用於調試的停止點上顯示本地語言,並且需要相應地使用DebuggerDisplayAttribute或更改方式您正在重寫ToString()。
就像其他人提到的那樣,調試器將調用ToString
在多個位置可視化您的類。 這包括自動,本地和監視窗口。 如果您不希望調試器調用ToString,或者不想在連接調試器時發生短路,則可以選擇幾種方法。
DebuggerDisplayAttribute
或DebuggerTypeProxyAttribute
您可以將這兩個屬性之一添加到類定義中。 在調試器中運行時,它將獲取這些屬性,並使用這些屬性提供的替代方法或格式字符串代替您的ToString()
方法。 下面顯示了表單Title
屬性。
[DebuggerDisplay("MyForm under debugger {Title}")]
public class MyForm : Form
{
}
Debugger.IsAttached
您還可以在ToString
方法的開頭檢查Debugger.IsAttached
屬性,並實現替代行為。
public override string ToString()
{
#IF (DEBUG)
if ( Debugger.IsAttached )
{
return this.GetType().Name + ": " + this.Title; // or something else.
}
#ENDIF
// The rest of your ToString implementation
}
將ToString()函數的名稱更改為其他
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.