Join Alexander Zanfir for an in-depth discussion in this video Named and optional arguments, part of Learning C#.
- As we've been developing the different apps for our different clients, we've been relying on word of mouth from the clients to tell us about any errors or bugs that might've come up and that's been working for us pretty good. But now that our client base is growing, it might be a good idea to roll out a system to track bugs for us. To do that, we can create the general logging system that we can then plug into our applications, which will log custom messages during the execution of our app, to the console and eventually to a log file.
So let's continue in our School Tracker Program and add a new class for logging. I'll call it logger. As our applications run, some lines of code might be higher priority than others and some actions higher priority than others. For example, if we get an unhandled exception, that might be a critical event we would need to log. So, we'll need to specify a priority type in our logger, so when we create the message, we can say whether it's low, high or critical priority.
Let's begin by creating a log function. I'll make it static and void and of course, public and I'll call it log and in here we'll have string with the message, but we also mention we're going to need the priority. Eventually we can use an enum, but for now, let's just use an int. So the next parameter can be an int called priority. Now another requirement for a logger is that we might want to track what class or system called the log function so that we know what system is actually logging at the moment.
Is it the payroll system? Is it our Student Tracker, or is it our console utility that would be good information to have in our log file. So let's create a third property, called system. That will be a string called system. And for now, we'll simply console.writeline the log. So I'll start with, system, then priority and finally, the log message.
And now let's apply those. And that should be it. So let's go to our program, and use our new logger. Let's open up the program class and let's go to the top of our main and specify that the program has started. So, I'll use logger.log and I'll specify that tracker has started and in a range of zero to two for priority I'll set this as one, since it's medium priority.
And the system will be School Tracker. Now let's copy this, and then let's go over to our payroll class and inside the constructor, at the end, after line 20, I'll paste in our log and specify payroll started and the system will be payroll. And now let's go into our pay all function and at the bottom, we'll copy it in again and then we'll specify pay all completed and this will be priority two.
And this is inside payroll and so on. We could actually populate dozens of these within our application, but for now, we'll leave it with three. Let's give it a try. And we can see that our logger is working and we're getting the correct system, priority level and our message. Now, if there's a crash, our clients can save this out and provide it to us as a log file, which we can then trace the execution of our program through the logger and see what the issue was.
But as we've seen, majority of the logs will be priority one. Since the average priority is medium, so, it would save us a little bit of time if we didn't have to type in one every single time and it would have that value by default. Let's take a look at how to do that. Let's go back to our logger class and we'll use an optional argument with a default value. So, let's go to the second parameter, which is int priority and now let's just set that to one.
As you can see, we have given it the default value, but as you can see, we're getting a compile error and if we hover over we can see optional parameters must appear after all required parameters. So, what we can do, is simply move our system, before the optional parameter with the default value. And now that continues to work. So, let's go back to our program and just move things around and since we have a default value for our priority, we no longer have to supply it as a third parameter.
And let's do the same inside our payroll. And since the priority is different for payroll, let's add that as a third parameter. Let's give that a try. We can see it's continuing to work. The next thing we can try to optimize is possibly providing a default value for system. Since our entire project is a School Tracker, we know that majority of the logs will come from the School Tracker as we see here in this log.
So, maybe we can create the property inside logger for the default system and then just use that instead of having to supply it every time. So, let's create new field where we can set the default system and it will need to be static so we can access it inside our static log function. It will be type string and I'll call it default system name and we'll set it to School Tracker. Now let's try to use it as a default value for our system parameter.
As you can see we're getting an error. If we hover over, we can see must be a compiled time constant, meaning that once it's set it cannot be changed. So let's go to line nine and add the keyword, const, but now we're getting another error that the constant cannot be static. That's because a constant is static by default so we can just take out the static keyword and now it should be working. So let's go over to our program class and since this is the default system we can take this out and now we just have a single parameter that we can use throughout our program.
So let's go down into our while loop, just before we start to add a new student and we'll log, adding new student. Let's give that a try. So we can see that our default value is working for School Tracker and we're getting tracker started and adding new student as a message. Let's try adding a new student. And there's the message again.
So it's still working. Now, what if we wanted to supply the priority, but use the default system name? Let's try to do that. So if I go over to our program and I wanted to change tracker started to level zero for priority. If I try to do that here, we can see that it's trying to set the system and not the priority because we can't access the third parameter without first setting the second. So we're forced to now supply the system name before we can set our priority, even though we want to use the default system name.
So to get around that, we can use something called named arguments and it's as simple as supplying the name and then colon, and now I've supplied the value for the priority argument. Let's give that a try. As you can see, it's using the default system name, School Tracker and the priority is set to zero.
Explore variables and data types; controlling program flow with conditions and loops; and building functions. Learn how to implement object-oriented programming such as encapsulation and inheritance in C#, and find out how to debug your code. Alexander then explores advanced concepts such as enumerators, ref parameters, interfaces, events, and abstract classes. In the last two chapters, he covers the "top" features introduced in the last several versions of C#, including lambda expressions and string interpolation.
- C# variables and data types
- Switch statements
- Object-oriented programming: encapsulation, properties, and inheritance
- Debugging C# code
- Advanced C# concepts
- Top new features