When stepping through my program the ToString() method is being called for no reason

Deadly 提交于 2019-11-28 09:47:41

问题


This is a bizarre problem I'm having even my senior programmer next to me is also confused. The issue in full is that somehow my ToString() method is being called and I don't know or understand how this is my code

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;
}

This seemingly random recurrence of the ToString() printing ONLY occurs when i step through the program. it will print on the line I designated above and also when the constructor exits and prints like crazy as I'm stepping through the ToString() method itself. I placed a break point in the ToString() but it will only stop on the breakpoint when the ToString() is legitimetly called, so to be clear when i step through and it does this random printing it will not stop at the breakpoints within the ToString(). I went through and removed all calls to the ToString() and it still get randomly called, when i commented out the returnString variable and just returned "her there" the problem went away but that doesn't help anything. if i just run the program without breakpoints this problem does not occur. some of you may say that if it works when running it doesn't matter but it makes me extremely wary that if i run into a code issue down the road and i try to step through the code to find the problem i will get different results and hinder the debugging. I tried cover the whole issue and what i have tried and provide all code needed, if i was unclear about something let me know and i will try to explain it again. lastly I am on a Windows 7 64 bit machine and I am using Visual Studio C# 2010 Express.


回答1:


You probably have a watch on the form, or are in some other way displaying it's value in the debugger (through the "locals" window, the stack trace, etc.). The debugger uses ToString to display objects. If this is a problem in your program, you should likely re-design your ToString such that it isn't a problem for it to be called like this, or else simply avoiding using the debugger.

Having a very "expensive" ToString that you generally wish to avoid using is a situation to be wary of. There can be occasional exceptions where it does make sense, but callers generally expect it to be a cheap operation. Consider whether or not it would be appropriate to have some other method/property representing a display string that is more involved, leaving a simpler/cheaper ToString implementation.




回答2:


The debugger may call ToString if you watch it or even if you just hover the mouse over the object. Usually it is a good idea to keep side effects in ToString at a bare minimum. I.e. ToString should not cause any state change.

A similar problem occurs if you watch properties and the get method has side effects.

Another problem is when using LINQ, since the debugger may evaluate the IEnumerable returned from an LINQ expression, which may cause all sort of side effects. With LINQ it may get even more tricky. If you have some code that actually rely on the LINQ expression being reevaluated (say some code that polls some LINQ expression until some condition is true), then you can gain some gray hairs when debugging, since the debugger may cache the expression and not re-evaluate it as you expect.

Another similar debugging nightmare: Debugging focus events. Very hard to do, since activating the debugger will steal focus and cause side effects. Sometimes good old-fashion print statements are the best option.




回答3:


I think that in order to display those DateTimes in Form(), the debugger is calling ToString() on them when you try to instantiate a new Form()... as @Servy has mentioned

Since you are using more than just strings in your Form() class, ToString() has to be called to display the locals in the stop point you've set for debugging and you'll need to use the DebuggerDisplayAttribute accordingly or change the way you're overriding ToString().

MSDN Ref




回答4:


As mentioned by others, the debugger will call ToString to visualize your class in multiple locations. This includes the Autos, Locals and Watch windows. If you don't want the Debugger to call ToString, or want to short-circuit when the debugger is attached you have a few options.

DebuggerDisplayAttribute or DebuggerTypeProxyAttribute

You can add one of these two attributes to your Class definition. When running in the debugger it will pick up these attributes and use the alternative method or format string supplied by these attributes instead of your ToString() method. The following shows the forms Title property instead.

[DebuggerDisplay("MyForm under debugger {Title}")]
public class MyForm : Form
{

}

Debugger.IsAttached

You can also check the Debugger.IsAttached property at the start of your ToString method and implement alternative behavior.

    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
    }



回答5:


change the name of ToString() function to sth else



来源:https://stackoverflow.com/questions/20980503/when-stepping-through-my-program-the-tostring-method-is-being-called-for-no-re

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!