You can tell that the Visual Studio team recognizes the primary issue C# developers face: finding the matching bracket. That must be true because the most obvious way of finding "the other bracket" is built into the way code is displayed: When you put your cursor beside one bracket (open or close), both it and the matching bracket are highlighted (or, because the default color for the brackets is gray: lowlighted).
Unfortunately, that isn't much help if the "matching" bracket is off the screen: you can't see the highlighting if the bracket isn't visible. In those situations my fallback method used to be the plus/minus signs in the left hand margin of the editor window: I collapsed my C# methods to see what code disappeared and what code remained visible. The problem here, of course, is that the collapsed code was often the code in which I was interested.
There's a third option that not a lot of developers know about: Place your cursor on the bracket you're trying to match (open or close) and press Ctrl+] (that's the Control key with a closing square bracket). Your cursor moves to the matching bracket. Pressing the key combination again takes you back to the bracket on which you started.
There are other benefits: If you're bored and stuck on a problem, I've found repeatedly pressing Ctrl+] and watching the cursor snap back and forth can be soothing. And, if anyone is watching, it looks like you're working.
Posted by Peter Vogel on 08/19/20150 comments
Developers frequently want to ensure two strings are identical without having to worry if some characters are in uppercase in one string and the same characters are in lowercase in the other string. Frequently, you see developers using either ToUpper or ToLower to avoid the problem:
If Name.ToUpper = OtherName.ToUpper Then...
But both ToUpper and ToLower create new strings, which is extra (and unnecessary) work.
If you can live with some extra typing, you can avoid generating those new strings by using the Equals method that every variable has, passing the InvariantCultureIgnoreCase choice from the StringComparison enumeration:
if (Name.Equals(OtherName, StringComparison.InvariantCultureIgnoreCase))
Now you have much less to worry about.
Posted by Peter Vogel on 08/12/20150 comments
The is keyword lets you check if a variable is pointing to an object of a particular class (or a class that inherits from some class). For example, the code in this if block only executes if CustomerVariable is pointing at an object of type Customer (or some class that inherits from Customer):
if (CustomerVariable is Customer)
{
...code to execute...
}
It works with interfaces, too:
if (CustomerVariable is ICustomer)
{
...code to execute ...
}
You can do your test and get a free cast from a variable by using the as keyword. If the cast fails, no exception is raised, but your destination variable is set to null, telling you that the variable isn't compatible with the object. The following code not only does what the previous code did, but also casts whatever object PremiumCustomerVariable is pointing to into CustomerVariable (if CustomerVariable and the object are compatible, of course):
CustomerVariable = PremiumCustomerVariable as Customer;
if (CustomerVariable != null)
{
...code to execute if PremiumCustomerVariable could be cast as a Customer...
}
If you want to do the same thing using the variable's class (rather than using some object as the previous examples did) then you want to use IsAssignableFrom:
if (typeof(Customer).IsAssignableFrom(typeof(PremiumCustomer)))
{
CustomerVariable = PremiumCustomerVariable;
}
This also works with interfaces:
if (typeof(ICustomer).IsAssignableFrom(typeof(PremiumCustomer)))
{
ICustomerVariable = PremiumVariable;
}
What other ways do you use to check? Share in the comments section.
Posted by Peter Vogel on 08/04/20150 comments
I suspect I'm like most developers and keep Visual Studio open and maximized all day (in fact, I've written at least one tip about how to get even more room to edit code). But, I admit, sometimes I switch to other programs. And sometimes, when switching between windows isn't good enough, I need to see that other window beside my Visual Studio window.
You could fiddle with your mouse and window borders. Or, you could hold down the Windows key and press the left arrow button (win_left). The current window will be moved to one side of your screen, have its height set to the full height of your screen and its width set to half of the screen's width. If you switch to another window and press win_left the same thing will happen to that window -- but it will be moved to the other side of your screen so that the two windows display side-by-side. If a window was in maximize mode, it will be taken out of it.
As you might suspect, other combinations of the Windows key and the arrow keys do interesting things. If you press win_up, the current window will be maximized. Both win_right and win_down take the window back to its prior "non-maximized" state (and that half-window display that win_left put you in doesn't count as your prior "non-maximized" state).
And, yes, I realize this isn't really a Visual Studio tip since it works with every window.
Posted by Peter Vogel on 07/30/20150 comments
I admit it: I don't use the Watch window much. When I hit a breakpoint and want to know what the current value is in a variable that's near the breakpoint, I'll either type "?variableName" in the Immediate window or hover my mouse over the variable to have Visual Studio pop up a Data Tip with the variable name and value.
If you're a "hover your mouse" kind of person you should pay attention to the pushpin at the end of the Data Tip: If you click on the pushpin and switch it to the "upright" position, that Data Tip will stay on the screen. The next time you hit the breakpoint (actually, whenever you have that part of your code on the screen) the Data Tip will be there, displaying the current value of the variable. If you need to drill down into the variable, you can use the plus sign (+) at the beginning of the Data Tip to see the values on the item's properties.
You can do more with your Data Tip: When you hover your mouse over the Data Tip, a "mini-menu" of choices will appear just past the end of the Data Tip. The middle icon in this mini-menu will let you unpin the tip which does not, as you might expect, cause the tip to disappear. Instead, the tip just drifts off to the right and now appears whenever you hit a breakpoint in any code window. This can be very helpful when you're trying to check one variable's value against another or want to change the value of the variable in the Data Tip. The bottom option in the mini-menu, which lets you leave a comment to yourself, can also be useful if your memory is as bad as mine.
The Debug menu also has some choices for managing Data Tips (including exporting and importing Data Tips if you want to keep some around after your debugging session ends). Data Tips are not an unalloyed blessing, if you have long variable names (names are usually displayed with their complete namespace): If the name disappears off the right side of your screen you won't get a scroll bar that will let you move to the right.
Posted by Peter Vogel on 07/23/20150 comments
Within an Action method, you'll sometimes realize that the processing you need is in some other Action method, often in the same controller. ASP.NET MVC provides a couple of ways of transferring control from one Action method to another one, but, sometimes, the simplest solution is just to call the other method. In those cases, it's worthwhile to remember that when you call the View method in ASP.NET MVC, you're not actually processing a View. The View method merely creates a ViewResult object that, when you return it to ASP.NET MVC, causes ASP.NET MVC to find the View and process it.
In a recent project, many of my controller methods ended by redisplaying the initial page. I had already created a View that did that: It was the first View that's displayed by the controller (I called the Action method that delivered the View FirstDisplay). That method looked like this:
Public Function FirstDisplay (id As Integer?) As ActionResult
...code to load the result object with the data to display...
Return View("DisplayItem", result)
End Function
In my other methods, I could just call FirstDisplay to redisplay the page. FirstDisplay would return the ViewResult object with the correct data, so I just had to return the results of FirstDisplay to get the page I wanted:
Public Function Update (id As Integer?) As ActionResult
...code required by the action method...
Return FirstDisplay(id)
End Function
See? Recycling is good.
Posted by Peter Vogel on 07/15/20150 comments
In the bad old days of desktop applications, every form object in the world had a Dirty property that let you easily check to see if the user had made any changes to the data on the form. It's almost as easy with client-side code running in the Web browser, provided you use jQuery. This line finds every input tag and ties the tag's change event to a JavaScript function called flagChanges:
$("input").change(function ()
{
flagChanges();
});
That will catch your textboxes, checkboxes, and any other input item defined with an input element. If you also want to catch changes in other elements, you can selectively add additional jQuery statements. This statement will catch changes made from dropdown lists (defined with select elements):
$("select").change(function ()
{
flagChanges();
});
You can do what you want in your flagChanges function, but here's a version that shoves some bolded text inside another element with an id of ChangeTextDiv (based on the name, probably a div element):
function flagChanges()
{
$("#ChangeLabelDiv").html("<b>unsaved changes in page</b>");
}
You'll need to remember to clear that element whenever you let the user save their changes. That's what this line of jQuery does:
$("#ChangeLabelDiv").html("<br/>");
Posted by Peter Vogel on 07/07/20150 comments
In previous columns, I've discussed options in assembling your View from a set of partial Views. However, in all of those examples, I've been assembling a View on the server in response to a request from the client.
The cool thing is that you can also return partial Views to Ajax calls. Here's a getJson call to a ASP.MVC Controller's Action method that expects to get back a set of HTML that it inserts into a page's div element:
$.ajax({
data: InfoAndData,
datatype: "text/plain",
type: "POST",
url: 'MyController/MyAction',
cache: false,
success: function (data) {
$('#divDisplay').html(data);
}
});
The Action method, accepts the data from the Ajax call in the same way as it does any other request but uses the PartialView method to trigger processing of the partial View and have the resulting HTML sent to the client:
Public Function MyAction(InfoAndData As InfoClass) As ActionResult
... code to retrieve data based on values in InfoAndData ...
... load results ...
Return PartialView("MyView", results)
End Function
There are lots of things to like about this approach -- having your HTML generated in a View is consistent with the way that the rest of your HTML is created. You also have access to all of Razor's tools for creating HTML (including localization). Finally, of course, your client-side code is reduced because you don't have to write the code to insert each data item into the page.
But there are at least two things to dislike: The payload being returned (HTML + data) is almost certainly going to be larger than the equivalent JSON object holding just the relevant data. The cycles required to generate the HTML may or may not be equivalent to cycles required to insert the data/set up the HTML on the client.
However, the server-side cycles are on a shared resource while the client-side cycles are on the user's computer. Using server-side cycles makes your application less scalable (personally, I feel that the user's computer should be regarded as free, unlimited resource that should be exploited mercilessly).
For me, I like using partial Views enough (and regard the costs of sending partial views as sufficiently low) that I frequently use this technique.
Posted by Peter Vogel on 06/30/20150 comments
While everyone using the .NET Framework creates Classes, not many developers create Structures. For those of you who are creating Structures, Visual Basic 14 has some good news for you: You can now give your structure a constructor that doesn't accept parameters (a default constructor). Formerly any constructor you added to a Structure had to accept at least one parameter.
Here's an example of a Structure with a default parameter:
Structure ProcessData
Private ErrorCount As Integer
Sub New()
ErrorCount = -1
End Sub
End Structure
If you want to have your default constructor actually execute, however, you must use the New keyword. This code will call the constructor and set ErrorCount to -1:
Dim pd As New ProcessData
This code will not:
Dim pd As ProcessData
and it will still run. Nifty, right?
Posted by Peter Vogel on 06/18/20150 comments
Years and years ago, I talked about how interfaces and inheritance were tools for making different objects look alike. Using interfaces and inheritance this way allows you to process a heterogeneous group of objects using a single variable.
In that column, I also pointed out that you sometimes needed to determine what the underlying class was for a group of objects that all looked alike to you. The TypeOf keyword is primary tool you have for determining what class an object "really" is.
However, if you were doing a negative test with TypeOf, you had to write some pretty unreadable code. This example tries to determine if the object pointed to by the cust variable is "really" a PremiumCustomer:
If Not TypeOf cust Is PremiumCustomer Then
Visual Basic 14 now lets you use the IsNot keyword with TypeOf so that you can write this more readable version:
If TypeOf sender IsNot Button Then
Visual Basic just gets better and better.
Posted by Peter Vogel on 06/11/20150 comments
I'm not a big fan of commenting code, which means that when I feel the need to add a comment it's because I feel that the comment is critical to the code's future. As a result, I want any comments I add to have maximum impact/usefulness.
In Visual Basic, however, I can only put comments before or after the statements that I want to comment. This is especially limiting in LINQ queries, which I often break up over multiple lines, putting each LINQ clause on a different line. This means that a comment on the line before the LINQ query may be explaining something three or four lines farther down the screen.
With Visual Basic 14, I can finally put my comments where I want them: In-line with the part of the LINQ query I want to explain. This example uses a comment to explain a Where clause:
Dim PremCusts = From c In db.Customers
Where c.Id % 2 = 0 'Premium customers have an even numbered id
Select c
You can also use in-line comments when you break up a statement over multiple lines using implicit line continuation.
Posted by Peter Vogel on 06/09/20150 comments
In Visual Basic 14, can now have read-only auto-implemented properties: Just add the ReadOnly keyword to the Property declaration. Here's an example:
Class Customer
Public ReadOnly Property Id As String
You can set the property by name from within your class' constructors. This example sets my Customer's Id property:
Sub New(Id As String)
Me.Id = Id
End Sub
From elsewhere in your class, you can not set the property's value using the property's name. This code won't work anywhere outside of the class' constructor:
Me.Id = Id
However, you can access the backing field for the property and set the property's value through that. The backing field will have the same name as the property with an underscore prefixed to the property name.
This example updates my read-only Id property through its backing field:
_Id = "Fred"
On a related note: If you have an interface that specifies that a property is read-only, in Visual Basic 14 you don't have to honor that restriction when you implement the interface in a class. The interface that specifies a ReadOnly property will be happy with either a read-only or a read-write implementation in the class that implements the interface.
Posted by Peter Vogel on 05/29/20150 comments