I have a System.Collections.Generic.Dictionary object in my code and am trying to view its contents while stopped at a breakpoint in the Visual Studio debugger. The Dictionary class in .NET of course contains a list of keys and values.
If I right-click on the loaded object, and try to drill down into its contents, I seem to get into an infinite loop. For instance, if I'm trying to see the contained keys, I expand the Keys element, which shows me a count, and another collection called "Non-Public members". I expand the latter, and get another dictionary object, which has a Keys element, which I can expand to get another instance of "count" and "Non-Public members", which I can expand, etc., etc.:
Using QuickWatch gives me the same result, so how do I actually view the keys contained in the object?
I know this issue is fixed in later versions of Visual Studio. However, for some of us who are stuck in an older version of VS here is a quick fix to see the keys of a dictionary.
Let's say we have a dictionary named 'dict'. We need the keys to see the values. So in a watch window do this:
dict.Keys.ToList()
That will allow you to drill down into the list and see the keys.
If you know the index of the key you want to you do the following:
dict.Keys.ToList()[1]
This will display the key at index 1.
Now you can take that key and see what the value is with:
dict[dict.Keys.ToList()[1]]
Of course you can replace the index into the keys list with the actual key value in another watch line if that is easier.
EDIT:
In addition, it is also possible to see the entries of a dictionary with the following in the watch window:
'dict.entries'
This will give you a list of entries to look through. Each entry will have a 'key' and 'value' property.
Related
I'm using my first dotnet TreeView and I have a problem with ImageList Keys.
When I write this code :
int i;
i = MyIL.Images.Add(Properties.Resources.CheckedItemBitmap, Color.White);
MyIL.Images.Keys[i] = "Checked";
The key is not written. I mean that MyIL.Images.Keys[i] is still empty after that code. It looks like that it is read only. But the documentation says that one can set values in it.
This is a problem because I want to use this specific overloaded ImageList.Images.Add() function, that doesn't let me specify the key value.
This is not the end of the world, but any clue would be appreciated.
As you observed, according to the documentation, the Keys property is read-only. The key is normally something that is set when you add the item to the collection, and sure enough, there is an overload of Images.Add that accepts a custom key. So I would use that overload, and set the transparent colour in a separate call:
Properties.Resources.CheckedItemBitmap.MakeTransparent(Color.White);
MyIL.Images.Add("Checked", Properties.Resources.CheckedItemBitmap);
Could someone help shed light on what is going on here?
If I do this in a C# program:
dynamic data = Json.Decode("{\"myObjects\": [ { \"id\": 1 }, { \"id\": 2 } ] }");
int id = data.myObjects[0].id;
I am able to access id and it is set to 1... everything is fine up until this point.
What I don't understand is why, when I'm debugging the program, I cannot view the contents of datain the Locals inspector. Instead it tells me this, as if it doesn't know how to process the array.
Error No further information on this object could be discovered
'data' is declared as dynamic type and thats why you cannot mouse over and see the value. You could still see the value if you add 'data' to Watch.
There seems to be a bug/limitation of Visual Studio (at least the 2013 version I use). If you put a watch on data, you can click on Dynamic View and see that it has stuff, but if you click on myObject (that is a DynamicJsonArray) you only get its "dynamic" part, and not its "fixed" properties (like the Length) and if you try to click on its Dynamic View you receive No further information on this object could be discovered... but if you create a watch for data.myObject, then you'll still have the unusable Dynamic View, but you can look at the "fixed" properties of the DynamicJsonArray (like the Length) and if you click on the Result View you can see the items of the array. See image:
The other answers did not work for me, but I found an alternative way to view the array contents in Visual Studio.
I have found that we can see the contents of the DynamicJsonArray in the Watch window (or IntelliSense), by looking inside the Non-Public members of the top level object. Inside that, we see the private _values member and inside that, we see the values. Upon opening the relevant value, we see the Key and Value members inside.
We can then proceed to open the Value node and then, the Results View, which will show the items in the array. We can then finally access the individual items in the collection
I have a class contains a lot of properties. One of them needs a special UI to be edited.
The user may press edit to this property in the UI then he make changes and either press OK or Cancel
e.g.
class A{
private List<Employee> employees;
public void EditMyEmployees(){
EmployeeEditorForm editor = new EmployeeEditor(employees);
if(editor.ShowDialog() == DialogResult.OK){
employees = editor.GetEditedEmployeesList();
}
}
}
The problem in the previous code that the editor has a copy of the reference to the employees List
and when the editor makes any edits in the List it will be reflected in the original object.
So, pressing OK or Cancel will have the same effect (the object is already updated) and no need for the step
employees = editor.GetEditedEmployeesList();
I know that making deep copy for the employees array before sending it to the editor will solve the problem but still I think this is not the efficient way to do it
I am looking for a design pattern that can make this in a better way.
You don't necessarily need to deep copy the whole collection. You just need to keep track of the elements that changed. Within your EmployeeEditor, use three lists (List<Employee> to keep track of:
Added employees
Removed employees
Changed employees
Upon Cancel, you would need to remove the "added" items, add back the "removed" items, and replace the changed items with their original state.
Note that the changed employees list would need to keep a copy of the original state of the object. If the Employee class has some sort of unique id, you can match cased on that id. Otherwise, the "changed" list would need to be a List<Tuple<Employee, Employee>> so that you can store the matching items.
Also note that, when changes happen in the employees list, you also need to make necessary changes in those three lists. For example, if an new employee is added and then removed, you also need to remove that record from the "added" list. Or it is possible an employee is changed and then removed, in which case you also need to remove from "changed" list.
Having said all this, if I were you, I would make a decision based on the expected use cases and real performance problems (not anticipated performance issues). It is very likely that simply deep copying your collection is the simplest and least error prone way.
There are two kinds of changes involved here: (1) changes to the list (Add / Remove) and (2) changes to individual elements of the list (employees in this case).
Now, part of the problem comes from the semantics of OK/Cancel. If you restrict the scope of these two buttons to changes of the second kind (i.e., changes to the elements of the list), you will be able to handle Remove with a confirmation dialog on this particular action ("Remove such and such"?). For the Addition you don't need anything special, just add a new element to the list. If the user changes their mind they will still have the Remove action available.
For changes on a particular element (second kind) you can use the command pattern as mentioned in the comment. More simply, you could initialize temporary variables for all the fields your editor displays from the element under edition. As the user modifies some values your editor will update the corresponding temporaries. If the user press Cancel you will simply forget those changes (or reinitialize them from the element). If the user press Apply (yes, you should include the Apply button also,) you will now write each of the temporary values onto the corresponding element's attribute. If the user hits OK you would Apply and Close.
I'm having an issue in a C# SQL CLR project where publicly declared Generic.List items are not showing up as public in the debugger. This is problematic because I'm trying to serialize the object to XML. The real project has some complex objects, but a very simple example would be something like this:
[Microsoft.SqlServer.Server.SqlProcedure]
public static void DoSomething()
{
// the Thing Object has a public property of List<string>
// that is created in the constructor
Thing t = new Thing();
t.Items.Add("test");
t.Items.Add("test2");
// now, if I look at t in the debugger, it has given the
// items list a capacity of 4 and shows the items as
// non-public members (2 with values and 2 that are null)
}
I wanted to post an image from the debugger here, but it appears I cannot do that as a new user...
With all of that said, is this behavior because it is a SQL CLR project? The same code worked fine when developing in a console application (though I guess I could have messed something up when adding it to the CLR project).
Adding additional detail on the Thing object - it includes the following declaration for the Items:
public List<string> Items { get; set; }
Then, in the debugger, the Items just shows Capacity and Count (no actual items or properties for the Items). The actual item instances are listed under Non-Public members.
The Items property itself can never be seen by a debugger, because it is an indexed property, so there isn't a value you can just get for it, and hence examining the value it returns doesn't make sense (like examining the 30th of February or a politician's kept promises; it just doesn't exist).
List<T> uses the DebuggerTypeProxyAttribute attribute to define another class to be used to give a debugger eye view. This class (one internal to mscorlib) has a public Items property that returns an array with a copy of the list's items, so that it looks like you can actually examine the Items property of List<T> when really you are examining the Items property of an object that copies out the items when invoked.
Debuggers don't have to use this approach, so maybe the one you are using doesn't, or there's some other restrictions, but if you are using a debugger that doesn't support DebuggerTypeProxy you can just examine the private member that stores the items in an array (the array will be at least as large as Count, and possibly a bit larger to leave growing room rather than resizing on each Add; you can ignore elements beyond Count - 1).
This has nothing to do with XML serialisation, so whatever problem you are having with that is likely completely unrelated.
Edit:
I see some people are having other problems with XML serialisation and the SQL CLR as per these:
SQL Server not finding serialization assembly
http://connect.microsoft.com/VisualStudio/feedback/details/753005/when-deploying-a-sqlclr-assembly-with-a-generated-xmlserializer-assembly-the-xmlserializer-assembly-should-be-deployed
http://social.msdn.microsoft.com/Forums/sqlserver/en-US/3fa5dce3-b0f3-44f8-9b7b-65439f1c98ae/cannot-deploy-xmlserializers-clr-assemblies?forum=ssdt
http://social.msdn.microsoft.com/Forums/sqlserver/en-US/e6560fa4-76f1-4da2-b795-7926d0743baa/sql-clr-problem-with-xmlserializer?forum=sqlnetfx
Your XML problem is indeed different to your debugger view issue. (I meanwhile am off to add debugger proxies to some of my collection types, I've always figured people would just skip through to the inner members and not care, but you've made me rethink that one).
In a Visual Studio Add-In that successfully creates a form, but gives me no reference back to the EnvDTE's prjItem instance.
Here's the piece of code that adds the form to the project:
string templatePath = solution.GetProjectItemTemplate("Form.zip", "csproj");
ProjectItem prjItem = project.ProjectItems.AddFromTemplate(templatePath, "myForm.cs");
Obs.: 'solution' is an EnvDTE80.Solution2 object.
Of cource I can get the reference by other ways, like proj.ProjectItems.Item([index]) (doing a loop and checking for names), but that's not how I want to do it, and I need this reference in orther to add controls to this form.
Am I doing something wrong?
Just found a comment on MSDN:
AddFromTemplate always returns a NULL
value
At one time, this was true. But
with later versions of Visual Studio,
which included the ability to add
multiple items from a single template,
the return value for this method could
not return multiple items. So it now
returns a NULL value in all instances.
This is due to the contraint that the
COM signature for this particular
method cannot be changed without
breaking a lot of code already in use.
Consequently, if you need the
ProjectItem interface of the item just
added via the AddFromTemplate call,
you can either iterate through the
ProjectItems collection, or you can
create a ProjectItemsEvents.ItemAdded
event just before calling
AddFromTemplate, and store away the
ProjectItem passed to your OnItemAdded
handler.
http://msdn.microsoft.com/en-us/library/envdte.projectitems.addfromtemplate(v=vs.80).aspx#1