I would like to display the current value of a class on screen for debugging purposes. For example, if I am dealing with the this class

public class Foo
        {
            public bool isSexy;

            public Foo()
            {
                isSexy = false;
            }
        }

and I wish to display the boolean parameter on screen how could I do that and have it automatically updated when its value changes?

I have a separate class that has a method of storing any parameter thrown at it in a dictionary

Dictionary<string, object> debugParams = new Dictionary<string, object>(15);

Any parameter is added to the dictionary with this method

public void AddParameter(string paramName, object param)
        {
            debugParams.Add(paramName, param);
        }

and displayed with this method

foreach (KeyValuePair<string, object> kvp in debugParams)
                        {
                            position.Y += 15;
                            string stringCurrent = string.Format(kvp.Key + ": {0}", kvp.Value);
                            spriteBatch.DrawString(font, stringCurrent, position, Color.White);
                        }

When adding parameters to the dictionary they don't update when the original parameter updates.

For example

Foo foo = new Foo();
            debug_Tools.AddParameter("Foo is feeling good?", foo.isSexy);
            foo.isSexy = true;

will display false, even though the parameter has been changed to true.

How can I fix this?

Recommended Answers

All 11 Replies

You could use
MessageBox.Show(parameter);
or you can use indents or whatever they are called by clicking on the left pane and you can hover over your variables for the values the hold.

The text needs to be displayed to the screen as the parameter might be updated 60 times per second.

For example it can be used to track object positions in real time instead of stepping through the code.

When adding parameters to the dictionary they don't update when the original parameter updates.

For example

Foo foo = new Foo();
            debug_Tools.AddParameter("Foo is feeling good?", foo.isSexy);
            foo.isSexy = true;

will display false, even though the parameter has been changed to true.

How can I fix this?

You're adding a boolean to the dictionary, which is a value type. The value is copied into a new memory location when it is stored within the dictionary, and any changes to the original value at the original location have nothing to do with the new value. It's just like saying this:

int a = 1;
int b = 2;
int c = 3;

List<int> list = new List<int>() { a, b, c };
a = 47;

foreach (int item in list)
   Console.WriteLine(item); // would write 1, 2, 3

I changed the value of a, but that makes no difference within the list because what I stored in the list was a copy of the value, not a reference to it.

Foo is a reference type, so if you were to instead store foo within the dictionary and then later change the value of foo.isSexy, the dictionary object would also reflect that change.

Is there anyway to pass the parameter by reference when adding to the dictionary, and still use object so any parameter can be passed?

ref foo.isSexy and using object?

If nobody knows of a way to use ref in this scenario, is it possible to automatically find which class the parameter is associated with and pass that into the debugger?

This way the class with always be a reference type and the parameter will be updated as normal right?

So say I pass just the boolean isSexy parameter into the AddParameter method, the method then ascertains from which class the parameter is associated with and stores that instead.

You're simply going to have to force yourself (or your users) to provide reference types rather than value types. You cannot add "ref" variables to a dictionary, nor can you determine from a parameter what its parent is unless, of course, the parameter argument has a "Parent" method or propety (there may be a way to accomplish it via reflection, but that's not a path I often travel).

You can at least restrict the AddParameter method to using reference types such as Foo by making it generic and then giving it a constraint.

void AddParameter<T>(T input) where T : class 
{
            
}

The where T : class constraint will force callers to provide a reference type. So passing in foo will work, passing foo.IsSexy will not.

Keep in mind, however, that if you ever came back later and said

Foo foo = new Foo();
foo.IsSexy = true;
AddParameter(foo);
foo = new Foo();
foo.IsSexy = false;

At line 4, you're setting foo to a new Foo object. The foo that you passed into your method and presumably added to a dictionary is no longer referenced by the foo variable in your calling method, so the dictionary object's IsSexy property would not be changed.

Thanks for the help here apegram. I've had an idea, please tell me what you think of this?

How about creating an IDebuggable interface which has references to the debug parameters

public interface IDebuggable
    {
        object DebugParam { get; }
    }

then a class can inherit from this interface.

public class Foo : IDebuggable
        {
            public bool isSexy;

            public Foo()
            {
                isSexy = false;
            }

            public object DebugParam
            {
                get { return isSexy; }
            }
        }

The new dictionary and AddParameter method would look like

Dictionary<string, IDebuggable> debugParams = new Dictionary<string, IDebuggable>(15);

        public void AddParameter(string paramName, IDebuggable debug)
        {
            debugParams.Add(paramName, debug);
        }


                        foreach (KeyValuePair<string, IDebuggable> kvp in debugParams)
                        {
                            position.Y += 15;
                            string stringCurrent = string.Format(kvp.Key + ": {0}", kvp.Value.DebugParam);
                            spriteBatch.DrawString(font, stringCurrent, position, Color.White);
                        }

I'm a pretty much a noob at C# but this method works. What's your opinion of this and how could I make this method more automated, or improve it?

Also, could I have more than one DebugParam in the interface without having to refer to it in every class that inherits from it? This is what I don't like about this method if not.

I would like to bump this thread. It seems to have dropped by the wayside and I was hoping for some opinions on the code above, from the resident coding gurus, before proceeding.

I don't think an interface is the way to go. I'm not suggesting I have a better solution, but perhaps consider using something like this:

class Foo
{
    public bool IsSexy { get; set; }
}

...

Dictionary<string, Func<object>> dictionary = new Dictionary<string, Func<object>>();

Foo foo = new Foo ();
foo.IsSexy = false;

dictionary.Add("foo", () => foo.IsSexy);

foo.IsSexy = true;
Console.WriteLine(dictionary["foo"]());

The value of the dictionary being a function that accepts no parameters and returns an object. In the lambda world, that is this: () => foo.IsSexy .

The reason this works is that by using a function and a lambda, the variable (foo) is being captured. As a result, evaluations of the function will always point to the present value of foo.IsSexy, not just the value of foo.IsSexy at the time it was added to the dictionary. This will allow you to also add multiple "debug parameters" to your dictionary for any given object, should you so desire.

Edit: Also, note how the function gets invoked. Since the value of the KeyValuePair is a function, you invoke it by the key dictionary[key] and the same way you invoke any function that accepts no arguments () dictionary[key]()

commented: I didn't know of lambdas until I read this. Very insightful! +1

That works great!

I'm I right when I say there is no way to pass just an object's parameter to the AddMethod class which will then update automatically?

For example

public void AddParameter(string paramName, object debugParam)
        {
            debugParams.Add(paramName, () => debugParam);
        }

will not update.

EDIT:

Thought I'd try this, but it doesn't work:

public void AddParameter<T>(string paramName, ref T debugParam)
        {
            debugParams.Add(paramName, (object)debugParam);
        }

That would not work for value types and is only loosely functional for reference types. You want to capture the original variable, not a copy of it, because the copy is not going to follow the changes of the original.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.