 Hello everybody, welcome back to the Virtual.NET conference of 2019. My name is Leslie Richardson, I'm a Program Manager on the Visual Studio Debugging and Diagnostics team. In this session, I'm going to teach you some tips and tricks for.NET Debugging and Visual Studio. So debugging can be really tough and really frustrating. Chances are you've spent a lot of time debugging issues in your code, and you just want to get back to coding as usual, right? So hopefully some of the tools that I showcase today will help you out and make your experience a more efficient and fun one. So there's a lot of ground to cover today and very little time to do so, so we're just going to jump right into demos. So for this session, I'm going to be using the latest version of Visual Studio 2019, and I'm using an ASP.NET Core 3.0 application that will randomly take in a list of books that I can either choose to read and add to my shelf, or choose to reject and they won't be added to my shelf. I love to read so this application is right up my alley. The problem is there's a lot of issues going wrong with it, and I want to use some of the tools in Visual Studio in order to figure them out. So I already have a breakpoint set at the end of this book manager constructor. This is a constructor that's taking in a JSON file with all my relevant book information, converts each of those into a book object, and then stores each of those book objects into a list called books. So books is the first variable that I would like to inspect. So I'm going to hover over books here, pull up its data tip which I'm going to go ahead and pin because I'm going to be using this more than once. Now when I expand this out initially, it's not very useful. If I wanted to identify each book by its title, for instance, I could do that but I would have to expand each and every one of these out, which can be really annoying and tedious. I have 100 books in this list in particular, so that can take some time. This also goes if I were looking at the same view in the locals or autos windows. So as an alternative, C-Sharp has an attribute that I can use called DebuggerDisplay, and this is an attribute that will allow me to customize how I view my objects in the watch, autos, locals, and data tip windows. So to use it, I have to stop debugging, go to where I defined my book class, and at the top of that class definition, I'm going to add some DebuggerDisplay syntax, and the brackets will return the value of whatever variable that I specify. In this case, I want to identify each book by its title property. So I'm going to type in title and continue debugging here. So technically, you can perform the same behavior by simply overriding your two-string method, but if you want to have that separation between the strings that you're viewing while you're diagnosing your code versus the strings that two-string is displaying in your actual application, then using DebuggerDisplay might be the better option. I'm going to wait for it to load. For those of you wondering, this is a feature that has been in Visual Studio for a very long time as well as just G-Sharp in general. So this is not an exclusive tool that you should definitely check out because here's the final product. I've stopped at my break point again. This time when I expand my data tip, I get a lot more helpful information. So as you can see, I can now quickly identify each book based off of their title. This goes for if I were looking at that in the locals window or the watch window or autos as well. So it's one of my personal favorite attributes and hidden features in Visual Studio, but there's a couple cons with this. Number one, you have to modify your code in order to use it, which depending on your project or depending on who you are, this may not matter, but if it does matter then that can definitely be a problem. Number two, you have to stop debugging in order to use it. So if you didn't plan ahead when defining your class from the get-go upon and you want to use DebuggerDisplay later, you're going to have to stop what you're doing and then add in this code. Then number three and most importantly, it's not the most discoverable thing to begin with. So you either know this feature or you don't, and you need to be familiar with the syntax in order to use it. So based off of all of those cons, and after listening to a lot of your feedback and your reactions to when I've discussed this feature in the past, we are currently working on a brand new feature that can perform the same behavior that can hopefully make the experience a lot better, that you can now get a sneak peek of right now. So in this version of the experience, you can perform that same behavior that DebuggerDisplay does except you can do it in the locals, autos, or watch windows. So for instance, if you wanted to favorite a particular property, say the language property as displayed here, you can click on this pin icon that will display, or you can right-click on a context menu option, and then when you click the pin, you'll get that same behavior where that property will show up under your value column in any of those windows. So this is really great because one, you don't need to modify your code to use it, you can perform this behavior while still in debugging mode. Number two, you don't need to stop debugging in order to run it. Number three, hopefully it's a lot more discoverable at the end of the day. If you play around with locals, autos, and watch windows a lot, chances are you'll have this pin pop up just at will and you can say, hey, what's that? Maybe I should check it out, and that should help alleviate some of those issues. All right. So now that I have gotten my ideal debugging environment set up in the form of debugger display, I'm going to hit F5 to continue running this code and try to identify some of the other issues that I'm having. So as I mentioned before, this is an ASP.NET Core 3.0 application that will randomly give me a list of books that I can either choose to read or not read. In this case, I'm going to say that I want to read this book called Sentimental Education, which sounds riveting. I'm sure it's a fascinating read. I have no idea what it's about, but I'm game. I click on it and the first issue that I'm having has to do with this read one-time string here. So this is a value that's supposed to increment every time I say that I finished the book, because anytime I read a book that I like, chances are I'm going to read it multiple times. At first glance, I'm already getting the red flag of it telling me that I've read it already even though I just added it to my shelf, but I'm going to click that I finished this book anyway. When I go back to it, I expect it to say that I've now read it twice, but now it's telling me that I've read it four times. So I either read this book three more times within the past five seconds and was slightly not conscious or there's something going on in my code that's causing a property to be modified without my knowledge. So it's probably the latter. So let's check out Visual Studio to figure this out. So I don't need this breakpoint anymore, but I do need to set a breakpoint at the end of my index function here. This correlates with my home page, so I just need to restart the page in order to hit it. From there, I want to hone in on that particular book, and just to get a sense of what's going on and try to solve this problem. So normally, this would be the time where I can expand out this My Shelf variable and locate the book that way. But another and faster way that I can use, that's new to 2019, is the new search feature for the local's autos and watch windows. So I'm going to type in education. There we go. As you can see, I'm immediately directed to the place where I want to go, which can save me some time. This is especially useful if you have hundreds of items that you're looking at at any given point in time or you have a list containing lots of different items and you don't want to have to go through the trouble of expanding each one of these out. So from there, I'm actually interested in looking at this objects times read property. This is the property that's supposed to increment every time that I say that I've finished the book. So I'm going to search for that again, and as you can see, I'm taken to where I need to be. Now at this point, I want to locate where this times read property is being changed. The problem with that is I don't really know where that change could be coming from because I wasn't expecting it. So normally, I could just set a regular breakpoint on this property setter, but I don't necessarily want to do that because that might mean that I could have hundreds of my book objects accessing that particular setter at a given point which can make my debugging experience a little noisy. So instead, I can use a new breakpoint available for .NET Core 3.0 called a data breakpoint. This is a breakpoint that will allow me to halt my code on a specific object's property whenever it changes, even if that property goes out of scope. So I'm going to use that in order to determine where that change could be coming from. So to use the data breakpoint, I can right-click on the property and then select break when value changes. I know that the data breakpoint has been created because I get the standard breakpoint icon next to the property. I can also view it in the breakpoints window right here. If I scroll up a little bit, you'll notice that there's an object ID, the dollar sign one here that has been added, and this is how Visual Studio will be able to keep track of what this object is doing if it ever goes out of scope while my code's running. So now that I've set that data breakpoint, I'm going to hit Continue on my code, and hopefully the next time I perform an action that triggers that data breakpoint, I'll get some more useful info. So I'm going to click on the book again, and right off the bat, I get a data breakpoint notification that's telling me that it was hit. So as an added bonus, it will tell me what the previous value of that property was as well as what the new value is. In this case, Times Red has been incremented from 4 to 5, and I'll be redirected to the exact line of code where that change came from. So in this case, it's happening in my property setter, which makes total sense, but I'm more interested in determining what last called that property setter. So I'm going to go into my call stack window, and then select the frame right below the one that I'm currently at, and then I'm taken to the line of code that last called that property setter. So in this case, Times Red is being incremented under my get-shelves-book method, which I don't want because I already have Times Red being incremented somewhere else. So I'm going to comment this out, and that should solve the problem, and we're going to restart. So data breakpoints are super cool. They were originally a C++ exclusive, but as of 2019, we've added them for .NET Core 3.0 or higher, and since 3.0 is finally out of preview mode, there's no excuse. You should definitely go try out data breakpoints if you're curious. Yeah. So it's really cool. I'm going to comment, or I don't need that breakpoint anymore, so we're going to keep running. Now I'm going to perform that same behavior again. So I'm going to select this book called the recognition of Shakunthala, forgive my pronunciation. We're going to click on it, and say that I finished the book, then go back, and as expected, it now says that I've read the book one time. So those data breakpoints and search for the watch window, both are 2019 exclusives, super cool. Data breakpoints you can use for several cases. In this case, I used it because I realized I could solve my problem by just honing in on a specific object. You can also use it if you have a global variable that's being accessed across multiple files and multiple methods, and you can also use it if maybe you've just inherited your co-worker's code and you're unfamiliar with the code base, but there's something going on in it that's causing the property to change in the spot that you're unaware of. So you can use a data breakpoint to determine where that location is, even if you're unfamiliar with the code. All right. So the next problem that I want to look at has to do with the line directly below where it says read one time. So I like to read a lot of books at the same time, and as a result, I can finish several books in the same day. So just getting the date is not specific enough for me. I want to know what time I finished each book. So I would like to add time to this string. So let's go into Visual Studio and try to break down that string in order to determine where I need to put that. So I'm going to set a breakpoint at this line that corresponds to that particular string display, and I can just refresh. Now looking at this right off the bat, there is a lot going on here. I've got several function calls, including a nested one here. I've got this time finished action. It's kind of a lot. So I'd like to break this down into smaller chunks in order to understand what's going on and to ultimately pinpoint where I need to change my code to add time-related info. So the first thing I'd like to do is step into the string function, but given the standard stepping options that I have step into step over and step out, I can't really do that because it's nested. As an aside, you'll probably notice that over where your stepping icons usually are in the toolbar, the icons have changed as of 16.3, and that's because we heard all of your feedback about how the previous icons in 2019 were not very readable, and I was one of those people personally. So we've reverted the icons back to what they were in 2017 to make that legibility experience a bit better. So anyway, I would like to step into this two-string function here, and so in order to do that, I can use a tool called step into specific, and this performs a step into, except I can pick and choose which functions I would like to go into first. So to do that, I can right-click on this line, and then go to step into specific, and then I'll get a drop-down containing all the different functions that I can choose to step into. So in this case, I'm going to go to person.to string, and just like I was performing, as if I were performing a normal step into, I'm taken to this function. This one's pretty basic. I'm just passing in my name and then it's being returned. So I'm going to step through it, and step right back out, no problem. So from there, I want to go into the finish two-string method, which is this hour function call. So I can use step into specific again to go into there, and here I am at finish two-string. So now I want to look at this string that's being concatenated, and normally this might be where I need to stop debugging and create an arbitrary variable that's equal to this value because I currently don't have one, and at first glance, it's kind of hard to see what the final value that's being returned is as just given this current view. But if you go into the autos, locals, or watch windows, I'm going to show you the autos and locals first, and step to the end of your function, you'll notice that at the top here, there's a little return keyword that appears, and so by default, the autos and locals windows will automatically give you what your return value is when you reach the end of a function, which is very helpful and requires you to not have to make variables that you don't want. You can also view the same return value in the watch window by typing dollar sign, return value, and you'll get that same deal. So the perk about using it in the watch window is that you can also add these things called format specifiers to this value, and these are little keywords that you can add that lets you further customize how you're viewing these variables in your watch window. So to do that, you can add a comma, and in 2019, you can get a nifty dropdown that tells you all the different format specifiers that you can use. So if you're unfamiliar with format specifier, then have no fear because this dropdown is here. And in this case, for instance, if I wanted to remove the quotation marks around the string, then I can go to NQ, which says string with no quotes, and I can select that one. And I mean, there's a bunch of different ones. So you can use nse, which stands for no side effects. So if you don't want to see any side effects in some of the variables that you're evaluating in the watch window, you can use that. Or if you want to see a decimal value that's converted into hex, you can use comma h to do that and so on and so forth. So definitely go try those out. They're really fun to play around with. Right, so from there, I now want to go into this finished book string, but the problem is I'm now currently at the end of this function. So I'm thinking I might have to stop debugging and then create a new session, which is not fun and run my code all the way back up to this line again. But instead, I can use something else called set to next statement. And this is a tool that will let me pick the next line of code that I want executed. So to use that, I can just drag my execution arrow here up to the line that I want to run next. So this is really great if you need to just quickly go back and reinspect something small in your code, but you kind of have to use this at your own risk because depending on what your code is, you're not actually rewinding back in your code. Instead, you're re-executing or you have the potential to re-execute things that have already been running. So depending on what your code is, this could easily create some side effects that you don't want to see in your code's execution that may result in you having to restart the session entirely, which is not great. But for here, it's totally fine. And from there, I'm gonna step in right here. So I'm at my finished book, string method. And now I'm gonna step to the very end of this function. And as you can see with return value, I'm getting the return value of my function, which is also very nice. And from there, I'm noticing I have this two short date string function call. And I think that's what's causing the time to be omitted. So if I get rid of that, then time should be displayed the next time I refresh. Now at this point, I just modified my code, so now would be the time to start a new debugging session. But actually, I can use the existing feature called edit and continue, which will allow me to continue running my code because Visual Studio will actually recompile the changes that I just made in my code so that I don't need to stop debugging. So this only works for certain scenarios, but it's really cool when it works. And speaking of that, we've gotten a lot of your feedback previously about edit and continue not working when it actually should be working. So as of 16.3, we've made a lot of improvements and changes to the tooling in that that will allow you to use edit and continue a lot more successfully. So if you've been burned by edit and continue in the past, definitely try to give it another chance and let us know your feedback about the update. So from there, I'm gonna refresh this page and I don't need this break point anymore, so hit F5. And as you can see, the time is now being displayed as I expected it to. So that's super cool. Lots of different features that I just mentioned there, set to next statement, set step into specific, return value, format specifiers, lots of cool things that you can play around with there. Now from there, I've actually gone and updated my code. I heard about that cool thing called asynchronous programming which I hear is all the rage so I wanted to try it out. So I've created a new branch called async and I've just modified some of my existing methods to make them asynchronous. But while I was making all those changes, I accidentally created some bugs that have been resulting and exceptions being thrown in my code. So let's take a look at some of those and how we can better diagnose those kinds of issues. All right, so back at my same application, so I've got the books. I'm gonna choose to read this book. It's got a weird name that I've never heard of. Right, and let's say that I finished it and go back. And yay, we get that lovely browser error that you've probably seen before if you've ever run an ASP.NET application. It's telling me that an unhandled exception occurred. So this isn't super useful because in my past experience, whenever I get an error such as like a null reference exception, I will automatically be redirected to Visual Studio and get like a nice exception helper notification telling me where that exception was being thrown from and I'm not getting it here. So there's a couple ways that I can get that exception to appear. The first one is by using the Diagnostics Tools window. For those of you who don't know what that is, it's that window that you probably found yourself closing in the past from time to time. I know I am also guilty of this, but it actually has some cool perks to it if we open it up. All right, so here's the Diagnostics Tools window and I'm gonna expand this up a little bit. And I'm interested in this Events tab here. So this is where Visual Studio was logging all major events that are going on as my code is being run and then I can go back and check out any of these, which is great. So I'm gonna filter this down to just my exceptions and you'll notice that there is one here that has a red diamond icon with a smaller camera icon here. It might be kind of hard to see, but it's there. So what's cool about this is that when my exception gets thrown, Visual Studio will take a snapshot or save the state of my application at that given point in time so that I can then go back and examine this exception further at the exact moment that it happened. So I can double-click on this and I'll be taken to the line where it was thrown and I'll also get the notification telling me that I'm now in historical debugging mode and because this was an exception that was thrown in the past. So that's super cool. If you're an enterprise user, then this is the way to go. So if you're not an enterprise user, what do I do? Well, the other option that you can use is the exception settings window. And in this window, you can perform an action called break when thrown. So in this case, I had an exception that was a runtime error. So I'm gonna check all common language runtime exceptions. And what I did there is I'm telling Visual Studio to stop my code the next time that a runtime exception occurs and it's automatically going to break my code at that given point. So to demo that, I can hit continue and I'll just refresh the page. And as I expected the first time round, I now get that helpful exception helper that gives me more information about that exception. And also just to talk about what diagnostics tools window works great as well is because I just threw another exception there and you'll notice another exception appeared under the event. So it's cool, I can go back and forth between any of those instances where those exceptions were thrown. So both of these options are really great for any kinds of exceptions that you see. The caveat for exception settings is that because I checked all runtime exceptions, I can expect to see a notification anytime any runtime exception occurs, which you may not want. That could happen pretty frequently depending on what the issue in your code is. So if you're more familiar with the specific exceptions that you're having issue with, then it's better to narrow it down and just check the ones, the specific exceptions that you want to have your code break out. So both of these are also great for your asynchronous code as well because while asynchronous code can be cool and while .NET and C-Sharp make it easy to incorporate in your current code using the async and task keywords, it also adds an additional layer of complexity to your code that maybe you didn't want. So in this case, Visual Studio was handling all those exceptions in runtime and as a result, I wasn't able to get this exception helper initially. So speaking of improving the async experience for debugging, another tool that we've been working to improve as of 16.3 is the Parallel Stacks tool for tasks window. So I have a gif of it running here, but in the new version, I can visually inspect all the different tasks that I have both awaiting and active and I can view their corresponding call stacks as well. So this is great if you want a visual representation of what's going on in your async code and trying to understand what actions are happening and what particular order. All right, so I have two more features that I want to quickly go through. The first is Source Link, which we've added to 2019 and this is a tool that when enabled, will allow you to hook up or sync up your DLLs or binaries no matter where they came from to your source code. So if you've wanted to debug a new good package or anything like that that's currently published out in GitHub or GitLab or anything like that, then you can enable Source Link in order to do that. And last but not least, my team has made an extension called the Child Process Debugging Power Tool. So if you've ever needed to debug processes that are being called by a parent of some kind, then check out this exception that's available for not just 2019, but pretty much every version of Visual Studio up to 2013. Super cool, my team gives it the seal of approval because we made it, so go check it out. And last but not least, if you want to experiment more and want to play around with the code that I was using in today's session, I have the links available for the master branch and the async version of that code as well. And from there, I hope you all learned something new and now I'll open it up to questions.