Documente online.
Zona de administrare documente. Fisierele tale
Am uitat parola x Creaza cont nou
 HomeExploreaza
upload
Upload




Handling Exceptions .net

software


Handling Exceptions .net

In this lesson we'll talk about handling exceptions within our applications. Now what is an exception? A very simplistic way of looking at it is something unexpected that happens while your application is executing. While this has become the default definition for the term, it's not entirely accurate.



An exception is a special kind of event that is raised by a method in a class. Whether the class is in the .NET framework or a class that you created doesn't really matter. It's an event that is fired because it either meets some condition or doesn't meet a condition that was expected.

It's up to every method of every class, whether we are talking about classes within the .NET frame work or even classes that you create, to decide when and why to raise an exception. Now usually it's because there is something about the state of the application or the values that were input into the method that are somehow invalid. Although that's not always the case. But at any rate, when this happens and it's impossible for the method to continue executing, the last thing that it can do is throw up its hands and raise an exception, hoping that the code that called that method can gracefully handle the situation.

So what happens is that you have a method, let say the button1 click event that we have been talking about up to this point and the event handler calls a method of some class in the .NET framework. Now we can build on the previous lesson. Let's say that this is the constructor of the system.xml.stream reader class. Now we pass in an invalid file location to the constructor and obviously there is a problem because the stream reader class can't continue on, so it throws an exception. And think in terms of throwing and catching a ball for example. The stream reader has to tell your code that something was wrong and that it couldn't continue executing. So it bundles up all the information that it can ascertain into a special object called an exception object.

[01:58]

The exception object is then passed to the code that originally called the method, hoping that it will know what to do. The code that you have written that calls the stream reader's construct method can just ignore the exception, or it can handle the exception. Now up to now, we have been ignoring all the exceptions, so our code hasn't been very robust, it's easily breakable. However, we can write some special code that checks just in case something bad happens as we're calling the stream reader method, and ensures that if something bad does happen our code can handle it.

We do this by using a try/catch statement within our code, and we will look at this in just a moment. So when we write code it is up to us to identify those lines of code that might be easily broken, and make sure to add these try/catch statements around them, and I will talk about how to identify them also later on in this lesson.

Let's talk about this exception class for just a moment. The exception class is the base class for all exceptions. So we have already encountered a few exceptions, for example in the previous lesson we saw the "file not found" exception that was thrown whenever the .NET framework tried to open an XML file but it could not find in the directory it expected to find it in. The file not found exception derives from the system.exception base class. Now why do you have to use specialized versions of the exception class? Why not just use the exception everywhere? It's really so that your code can determine the exact nature of the problem and resp 22222g61w ond to it accordingly. For example, if the exception is of type file not found exception, then there is an easy remedy for this problem. You tell the user, and then you allow them to find the file on their hard drive using some type of dialogue. Or perhaps the file is corrupt, and then there is a different exception for that which requires a slightly different error message to the end user, and perhaps a slightly different remedy in order to fix the problem.

[04:01]

Or perhaps the file doesn't contain any XML, or any of a number of possible that can occur. Now having the specialized version of the exception base class allows you to pick the right course of action and then try to handle it within your application if possible, and if its not possible then you can tell the user what the problem is and ask for their intervention, like "please pick another file."

So in the .net framework there are dozens, if not hundreds, of different exceptions that have been defined, that are all deriving from the system.exception base class, and whenever you create your own applications, your own classes, you can create your own specialized versions of the exception base class. Now we're not going to talk about how you can do that in this series of lessons, but on www.learnvisualstudio.net, we talk about that at great length. So let's continue on.

Let's talk about a best practice, and that is that you should anticipate the problems that can occur within your application. When you anticipate what those problems are, then you should write try/catch code around those possible problems. And if you can resolve the problems without the user's involvement then that's great; that's what you should do. If the problem requires the user to intervene, like please pick another file, then that is okay too. But you should never just allow the application to break and leave the user confused about what to do next.

So let me give you an example of what I mean. We're going to create a little application that will intentionally be easily broken and look at what happens whenever we don't handle the exceptions. And then we're going to wrap some try/catch statements around the code and see how to handle the situation a little more gracefully.

So you see that I have taken the liberty of creating a new project called Lesson11, and it is a simple windows forms application, and here I'm going to put a button, and I'm going to put two textboxes, and this is going to be just a simple calculator that will allow us to add two values together or multiply two value, whatever we choose to do.

[06:10]

Let's just drag and drop our two textboxes, and then I'm going to double-click on my button, and here I'm going to paste some code in. So you can see here that what I have done is to create a value called results and I'm going to multiply Textbox 1 times Textbox 2 after parsing the values in Textbox 1 and Textbox 2 to integers, and then I'm going to show the results into a string. Then finally in the last two lines of code I'm going to clear out the values in the textboxes. Now obviously this can be easily broken, because all I would need to do is to put in any alphanumeric character, not just a numeric character, and we have got problems.

So this works well, but this will not work well. You can see once we're in debug mode within our Visual C# 2005 Express Edition IDE that I'm going to get a real pretty message that a format exception was unhandled. Now what will happen here is that our end user will not see the same pretty message. So let's go ahead and stop the application right now. Let's find it on our hard drive by navigating to our Visual Studio 2005 projects, lesson 11 and then going into the bin directory, debug, and we're going to double-click our lesson 11.exe, and let's see what happens here. I'm going to put in "a" and then the number "7," and you can see that I get this very very ugly .NET generated exception message.

[08:05]

You can see here that you can find details, but its still not very useful to an end user because there is a lot of Information here that they would have absolutely no idea what it means. So you don't want your end user to see this, you probably prefer to put a more friendly message box that says, "Look, you are not using values that are acceptable to this application, try using numeric values only," or something to that extent.

So let's go ahead and quit that, and then rewrite our application or add some exception handling code around this, so that we can make this a little more user-friendly. The way this problem can remedied is by using what is called "declarative exception handling," through the use of the try/catch statement as we have indicated earlier. The try statement defines a code block that is watching for exceptions as they happen. If an exception is found, then the code execution is diverted from the current line of code to a catch statement. And you can have more than one catch statement to catch more than one specific type of exceptions. Or you can handle all the exceptions by just catching the base system.exception class. Let me show you how to do this and rebuild this example so that we can take advantage of this. I'm going to just drag a second button, double-click it, and now I'm going to paste some code into my button 2 click event. This time we still have on the first line, the creation of our result integer, and the next line of code is a try statement with an open and closed curly brace. Between that code block, we have the two lines of code that we saw in the previous example: result equals to int.Parse(textBox1.Text) and so on. Where we're multiplying textbox 1 by textbox 2, grabbing the result in the next line of code, and then displaying it in the message box.

[10:03]

Now if there is a problem within that try block of code, then an exception will be thrown, and now we're able to catch the exception. You can see here that I'm just catching a general exception - the base class. This will allow me to catch any exception class when that happens. Now I will show you why we want to be more specific in just a moment. But you can see here that if there is a problem, then I'm going to display a message box and just assume what the problem was. There's a problem with your entry and so on. And then finally the last two lines of code are where I clear out our textboxes.

Let's run the application one more time, and this time whenever I use an alphanumeric character instead of all numerics, I get a message box that is a little bit more friendly - "There is a problem with your entry. Please make sure you use numerical values."

So we're able to handle this more gracefully, my application is still running, and the user knows now that they can't input alphanumerical characters.

Now what I can do to even further extend this example is to add another catch statement. As I said just a moment ago, you can add multiple catch statements in order to narrow down the exact problem that happened within the try block of code. So here we go. Catch, and we're going to use the format exception and then define a code block for that, and I'm just going to copy this message box that we used here, and this time I'm going to change the general exception to remove some of the more specific text because we really don't know what the problem was. "We don't know what the problem was," and I think you probably want to be more specific than that, but that's the gist of what's going on here.

[12:05]

So let's set a breakpoint here within our code. Save it and then run our application, and this time I'm going to type in "a" & "7" and then click Button 2, and now you can see that I'm stepping through code. I'm going to use my "step into" button, and notice that immediately it jumps to the format exception catch block, where our error message is displayed, and then it just hops over the next catch block because we have found the most specific version of the exception, as opposed to the most generic; and then we can just continue on, I'm going to hit F5 on the keyboard and continue on.

So that really brings up a best practice. That I want to try the most specific exceptions first, and then the most general last. So you can see that here I'm catching format exception, and if there were other expected problems with these lines of code I could add additional catch statements. Finally, I'm using the catch statement that catches the general exception, exception ex, for the most generic exceptions that can possibly happen.

So the question comes up, first of all, how do you know what exceptions can possibly happen within your application? And that comes down to good testing. Whenever you are developing an application, you want to test and test and test the application. Be devious and think of all the ways to break the application - putting in too much information in the textbox, putting too little or no information in the textbox, using characters like alphanumerics and underscores and the @ symbol, and all the different types of things to try and break your application. And there are dozens and dozens of ways that we can break even the most simple application like this.

[14:06]

So it's up to you to become creative, and if you are not working within a team of developers, it is helpful sometimes to have a friend or two use your application for a while, see if they can break it. This is sometimes known as beta testing your application, by rolling it out to a select few individuals who would be willing to use your application for some time, before you offer the application to everybody that you know or everybody that's interested in using the application. And many of these types of things will come out during that type of testing, and you can then take that opportunity to recreate the problem, as you are testing on your computer, and find what the specific exception is that was triggered. And then catch that, and ideally in this instance, what we would want to do is just report the problem back to user.

But you might have the other creative ways to handle the problem. Maybe you happen to know that they were trying to hit, instead of the letter "a" than number "1." That's a big assumption for this particular application. But perhaps if a file is missing that was expected like we saw in the previous lesson, maybe you look at the parent directory and then ask, "Is this the file that you meant to use," or something along those lines. But find a creative solution to the problem and again, if the problem can't be remedied without the user's intervention, then bring the user in only after you've exhausted all the possibilities.

So you can see how to use the try and the catch statement. Let's now talk about throwing exceptions from a custom class that you build. So to illustrate this, what I've done is create a class called my class. In the definition of my class, I have added a single method that returns type double called my method that accepts a type double taxable amount. Then what I do is check the value of the taxable amount, and if the value is greater than one hundred thousand, then I throw a new instance of the "argument out of range" exception.

[16:24]

Now how did I find this? Well quite honestly, I just went through the intelle-sense and found an exception that already existed that kind of covered what I wanted to say within my exception. But I could have picked one of a number of different exceptions. This one seems to fit the best. You can see that I did something a little bit different in the next example where I showed the taxable amount is not less than zero. If that's the case, then I just create a generic exception, just the base class exception x = the new exception.

And then I pass in a string, which is one of the overloaded constructors for the exception object. And the string represents a message that the calling code can take a look at and then display to the end user, or just ignore it and log it in a log file, or whatever the case might be. If both of those tests are successful and we're able to execute the return statement at the very bottom, then we will just return the taxable amount times some tax rate, in this case 0.075.

Next I've added a button called Button 3 to my designer surface of my form, and then taking a look at the click event for Button 3, you can see first of all that I've created a variable called "taxable amount," that I retrieve the value of textbox 1 and 2 by parsing it into a double, and then I create an instance of My class - class that I created, and then I create a variable called "result" that I'm going to retrieve the result of y method into.

[18:05]

Then you can see my try statement where I'm setting the result equal to my class.my method, passing in taxable amount. Then I simply display it in the message box. Now the next two statements are where I'm actually catching the value from my Class. If the user were to type any value that exceeds the ranges that I have set forth within the mymethod method.

[18:31]

I can check for the argument out of range exception, or as you see here I just, in the second case, check for the general exception, and in that case I don't know what specific message to tell the user, so I'm going to depend on the message property of the exception to display to the user. This probably isn't the best idea, but it illustrates how to retrieve the message property from the exception object.

At the very end of my catch statements, you'll notice that I've added a new construct to our try-catch statement, and that is a finally statement. And we use a finally statement to execute no matter what will the outcome is, whether the try statement is executed successfully, or whether it is interrupted and a catch statement was executed instead. The finally statement runs at either of those scenarios, it runs no matter what. So in this case, what I want to do is set my instance of my class equal to null, which essentially then indicates to the garbage collector of the .net framework that it should be taken out of memory. Now it's not completely necessary that I do that, and I haven't shown you how to do that up to this point, but it is something that is considered a best practice to do. Once you are finished with your objects to set the references equal to null.

[20:06]

So now let's do this: Let's set a breakpoint here on this first line of code on the button 3 click event, and run our application. We'll put in some value, first of all something easy, 25,000 and then I'm going to click button 3, and we would expect this to execute successfully. And see now we're going through and checking the value of taxable amount, and so it will return successfully in a message box the value of the tax, 1875. Very good, and we will just continue run our application. Now let's put in a value of negative fifty and see what happens. Click Button 3 and step through our code again, and this time it should pass the first test but it won't pass the second test. So an exception object will be created, the message will be set in the constructor, and then it will be thrown to the code that called it, which is back in our button 3 click event. And you can see here that we're going to display the message property of the exception object that was thrown back to our button 3 click event in a message box, "The taxable amount must be larger than zero."

And then it continues on. Finally just for the sake of completeness, now let's do something like a 110,000, let me count the zeros, that looks right, and click button 3, and now we will run this again, and this time the first check to make sure the taxable amount is not greater than 100,000 will fire and will throw a new argument out of range exception. You can see that is then caught. The message box is then displayed, and then we're going to execute that last line of code.

[22:02]

My class equals null, and then finish executing. Now that I have taught you all the neat features of the try/catch statement you might be tempted to put them everywhere in code, but I would discourage you from doing that. The reason why you don't want to put the try/catch statement around every line of code that you write is because it is expensive in terms of processing power. It will make your application slower, and quite frankly, you don't need to wrap every single line of code that you write in a try/catch statement. You should only wrap those statements that have a propensity to blow up. So for example, you will notice in some of the code that I have written, for example this first line within the button 3 click event, that I didn't include this in the try/catch statement, where I'm taking the taxable amount = double.parse (textbox 1.text).

Maybe this would be a good place to put a try/catch statement because I need to determine whether or not the value is alphanumeric versus a numeric value that can be easily parsed into a double. So that might qualify, because we are depending on the input from the end user. However the creation of new classes, like I have done in the next line of code, "my class my class equals new my class." We wouldn't need to wrap that in a try/catch statement, nor do we need to wrap the next line, because these are not lines of code that would be easily broken within our application. Now whenever we're calling the my method method of my class and sending in the taxable amount, we happen to know that there is some error checking that goes on, so that might be a good place, but we really don't need to put the message box within a try/catch statement because that is something that can usually be executed without any problems occurring.

[23:53]

So there is some discretion that needs to be used whenever choosing the lines of code that need to be wrapped within a try/catch statement. Select those things that either accept input from the end user, rely on some external resource, or where there's some value checking that needs to happen, there's some sanity checking within the object itself, that we're calling a method of, so that we can then process what happens if that call doesn't work correctly. So if it's something that we can handle ourselves, we don't need to wrap a try/catch around it, but if we're relying on some external resource or the method of some class that we don't control or that we don't know that how it works, then we may want to wrap that within a try/catch statement.

So just whenever you are writing your code, be very conscientious about, "What is this line of code doing, and how could it be broken?" If you think that it can't be broken, if it is performing a simple calculation and you've already checked the values before you perform the calculation, then there may not be a reason to wrap a try/catch statement around it. However if this has a propensity to break when you are working with files, or user input, maybe you should think of wrapping it in a try/catch statement.

So we talked about quite few things in this lesson in regards to making your applications more robust, more stable, less easily broken, by introducing the concept of the try/catch statement, which is a form of declarative exception handling. We talked about the exception object, and how it's the base class for all the specialized exception classes that are used within .NET framework. We noted that we can create our own exceptions, although we didn't show specifically how to do that. Whenever creating our own classes, we can definitely use this to throw exceptions back to the calling code of methods within our objects. And we also talked about what happens when you don't try to handle the exceptions within an application. What ugly messages your end users will see and why it is a bad idea.

So if you enjoyed this video, please visit www.learnvisualstudio.net to download and watch over 500 videos just like this one aimed at all skill levels on many different topics related to C#, Visual Basic.NET, ASP.NET and more. Thank you.


Document Info


Accesari: 1426
Apreciat: hand-up

Comenteaza documentul:

Nu esti inregistrat
Trebuie sa fii utilizator inregistrat pentru a putea comenta


Creaza cont nou

A fost util?

Daca documentul a fost util si crezi ca merita
sa adaugi un link catre el la tine in site


in pagina web a site-ului tau.




eCoduri.com - coduri postale, contabile, CAEN sau bancare

Politica de confidentialitate | Termenii si conditii de utilizare




Copyright Š Contact (SCRIGROUP Int. 2024 )