I wanted to create a console app in Visual C# which required the app to choose a path based on the number of days elapsed between the current date and a date entered by the user. I assumed I would do a quick search and find a way to do this on MSDN or Stack Overflow. I assumed many people had done this many times and code snippets would be posted all over the web. Wrong. Sure, I found a way to subtract one date from another if I entered the dates as arguments or the app was a form. But I couldn't find a way to do it when 1) the app was a console app, 2) the app provided the current date and 2) the user entered another date which would be subtracted from the current date.
This is a two-part post explaining the program I wrote to resolve the problem. Part I explains how to get the dates. The second part will explain how to subtract the dates to get the time interval. The full source code is on GitHub.
Today is the day
Getting today's date is easy:
Console.WriteLine("Today's date is {0}.", DateTime.Today);
Microsoft has already provided us with the DateTime struct and its property, Today. By reviewing the source code, you can see that Today is a static property. Static properties can be called without an object being created, hence, the reason the code snippet above will display the current date and time.
However, for my purposes, there are a couple of problems with this code. First, this format will give you a time of 12:00:00 AM as well as the date. For my app, I didn't need the time. Second, I didn't need to merely display the current date, I needed to store it so that another date could be subtracted from it. As painfully obvious as this is now, I wasn't sure how to do that. If you aren't either, read on.
Construct Today
Starting with the basics, DateTime is structure (a.k.a. struct) in the System namespace. You do not need to use keyword "new" to instantiate a struct object. Create the object like so to display only the date:
DateTime dateOnly = DateTime.Today;
Console.WriteLine("Today's date is {0}.", dateOnly.ToString("d");
(The "d" is a short date format specifier. In other words, this format will give you the date and not the time.)
You may also want to read DotNetPerls which explains why you would choose the Today property over the Now property.
User Input
Since DateTime is a struct, that means it is a type. After I ask the user to input a date, I declare a DateTime variable and convert the line entered by the user to DateTime type. Just as with the code snippet above, though, this will display the date and a time. So the next step is to create a DateTime object and use the short date format specifier in the Console.WriteLine argument.
Console.WriteLine("Enter the date you bought your vehicle.");
Console.WriteLine("Use this format, 01/01/2011.");
DateTime whenBought = Convert.ToDateTime(Console.ReadLine());
DateTime boughtDateOnly = whenBought.Date;
Console.WriteLine("Vehicle was bought on {0}.", boughtDateOnly.ToString("d"));
Here is a screen shot of the output.
The next post will go over TimeSpan and its Subtract method.
Sharing my journey as I go from knowing almost nothing to, hopefully, a whole lot more.
Wednesday, May 21, 2014
Sunday, May 11, 2014
Optional Parameters and Named Parameters in C#
I just don't like it when simple things are explained in a complex manner. So let me break it down for other C# noobs, in case you have a textbook like mine that provides an insufficient explanation or if you just don't understand these two types of parameters.
Optional Parameters
You will be surprised to learn that, as the name suggests, this means the parameters* are optional. The client code does NOT have to provide arguments for these parameters. Why? Because a default value is already included for you.
Example: public void optParam (int x, int y =2, int z = 3)
{some code};//this method has two optional parameters
In this case, there are two optional parameters, "y" and "z". Parameter "y" has a default value of 2 and parameter "z" has a default value of 3. If no value is provided for "y" or "z", they will retain their default values. You will notice that parameter "x" has no default value provided. This means that the client code MUST provide an argument for this parameter. Also be aware that the required parameter must come before the optional parameters.
Obviously, there is a problem. If you want to provide an argument for "z" and not for "y", how can you make the arguments be evaluated so that the first argument will be applied to "x" and the second argument to "z"? You can't. As MSDN informs us, you would have no choice but to specify the argument for the optional parameter "y" before providing the argument for "z". Needless to say, there would be no point in having an optional parameter "y" in that case. This is where named parameters come to the rescue.
*Per MSDN, optional and named parameters can be used with methods, constructors, indexers and delegates.
Named Parameters
When calling the method, the client code need only name the optional parameters for which it wishes to provide a value, avoiding the problem just described.
Example: public void optParam (int x, int y =2, int z = 3) {some code};
optParam (20, z: 30);
This result is x = 20, y =2 and z = 30. You avoid having to rewrite the default value and another benefit is that you can put the named parameters in any order. The same rule about required parameters coming before optional parameters applies here. The arguments supplied for the optional parameters can come in any order as to each other, but they must come after the arguments for the required parameters.
Example: public void optParam (int x, int y =2, int z = 3, int zz = 5) {some code};
optParam (20, zz: 30, y: 10);//okay
optParam (y: 30, zz: 10, 20);//not okay
Here you can see a sample of code I wrote to show how the two types of parameters work together and a screen shot of the results: https://github.com/htravar/Parameters. You may also find this article helpful.
This topic does get more complex, but I hope I've explained the basics in a basic way. Enjoy the parameter shortcut.
Optional Parameters
You will be surprised to learn that, as the name suggests, this means the parameters* are optional. The client code does NOT have to provide arguments for these parameters. Why? Because a default value is already included for you.
Example: public void optParam (int x, int y =2, int z = 3)
{some code};//this method has two optional parameters
In this case, there are two optional parameters, "y" and "z". Parameter "y" has a default value of 2 and parameter "z" has a default value of 3. If no value is provided for "y" or "z", they will retain their default values. You will notice that parameter "x" has no default value provided. This means that the client code MUST provide an argument for this parameter. Also be aware that the required parameter must come before the optional parameters.
Obviously, there is a problem. If you want to provide an argument for "z" and not for "y", how can you make the arguments be evaluated so that the first argument will be applied to "x" and the second argument to "z"? You can't. As MSDN informs us, you would have no choice but to specify the argument for the optional parameter "y" before providing the argument for "z". Needless to say, there would be no point in having an optional parameter "y" in that case. This is where named parameters come to the rescue.
*Per MSDN, optional and named parameters can be used with methods, constructors, indexers and delegates.
Named Parameters
When calling the method, the client code need only name the optional parameters for which it wishes to provide a value, avoiding the problem just described.
Example: public void optParam (int x, int y =2, int z = 3) {some code};
optParam (20, z: 30);
This result is x = 20, y =2 and z = 30. You avoid having to rewrite the default value and another benefit is that you can put the named parameters in any order. The same rule about required parameters coming before optional parameters applies here. The arguments supplied for the optional parameters can come in any order as to each other, but they must come after the arguments for the required parameters.
Example: public void optParam (int x, int y =2, int z = 3, int zz = 5) {some code};
optParam (20, zz: 30, y: 10);//okay
optParam (y: 30, zz: 10, 20);//not okay
Here you can see a sample of code I wrote to show how the two types of parameters work together and a screen shot of the results: https://github.com/htravar/Parameters. You may also find this article helpful.
This topic does get more complex, but I hope I've explained the basics in a basic way. Enjoy the parameter shortcut.
Wednesday, April 30, 2014
Math.Min vs. Random.Next in C# - To be (static) or not to be?
As I carefully read through my notes, I had to stop and ask, "Why do I need to create an object for class Random? It bothered me to no end because I had just read about Math.Min being a static method. (Static methods mean you are not required to create an object prior to calling the method.) Yet here I was, perusing an example that created an object of class Random before calling the Next method.
My problem was my assumption. My assumption was that Random.Next was a static method since I had just been reading about static methods in a different section of my lesson/text. It was not explicitly pointed out that I was no longer reading about static methods and I just assumed every method discussed was static.
As a lawyer, I should have been more discerning. Luckily, the light bulb went off and I started a search for "Is Random.Next a static method in C#?" Turns out, I was not the only one who had this question. Stack Overflow turned up first in my search and someone asking the same question received enlightening answers on why Random.Next cannot be static. Although it would have been nice if someone had noted that we were no longer talking about static methods, the fact is that Random.Next was actually discussed in a section on the .NET framework class library in general, not in the section on static methods.
So, for all you noobs who were perplexed as I was, the answer is that Random.Next is not a static method. This is why you must create an object before calling the Next method. Just watch what you're reading and don't assume too much.
My problem was my assumption. My assumption was that Random.Next was a static method since I had just been reading about static methods in a different section of my lesson/text. It was not explicitly pointed out that I was no longer reading about static methods and I just assumed every method discussed was static.
As a lawyer, I should have been more discerning. Luckily, the light bulb went off and I started a search for "Is Random.Next a static method in C#?" Turns out, I was not the only one who had this question. Stack Overflow turned up first in my search and someone asking the same question received enlightening answers on why Random.Next cannot be static. Although it would have been nice if someone had noted that we were no longer talking about static methods, the fact is that Random.Next was actually discussed in a section on the .NET framework class library in general, not in the section on static methods.
So, for all you noobs who were perplexed as I was, the answer is that Random.Next is not a static method. This is why you must create an object before calling the Next method. Just watch what you're reading and don't assume too much.
Friday, April 18, 2014
Construction Junction in C# - For Beginners
In my Intro to C# class, I felt like I was weaving through a maze when it came to reading the code that brought together the concepts of properties, constructors, methods and objects. It's not really that confusing, once you connect the dots. So let's pretend the world is ending and see how these things work together.
In the post prior to this one, you will see code that includes class Zombie and class ZombieTest. Or get it here: https://github.com/htravar/Zombie. Don't let the fact there are two classes freak you out. Think of it this way - class Zombie contains the general instructions for what the program should do and class ZombieTest gives class Zombie specific data to carry out the program.
Class Zombie
The properties "Relations" and "RelativeName" (lines 9-10) are auto-implemented. This means that instead of writing out the private instance variables and the properties separately, we skip writing out the private instance variables and we skip writing out the get and set accessors. You know when you see auto-implemented properties that private instance variables of the same name have been created for you. (Note: There are times when you will want to add code to your accessors and you will not auto-implement. That is a topic for another day.)
Next we come to the constructor (lines 12-16), which you will recognize because it has a) the same name as the class, b) does not have a return type like method and c) it has parameters. If it did not have parameters, it would be a default constructor. A default constructor is provided by the compiler when you do not provide one yourself. The default values are null or 0. Here, I want to initialize the object with some values other than null or 0, so I have created my own constructor with parameters "name" and "relationship" (line 12), both of type string. For more info on constructors, see http://www.dotnetperls.com/constructor.
Now we connect the first two dots, the properties and the constructor. In the constructor, I use an assignment statement (line 14) to give the property "RelativeName" whatever value is passed to the constructor's parameter "name". Likewise for property "Relations" and the parameter "relationship" (line 15).
We'll come back to how we get the relative's name and relationship actually into the program. For now, we move on to the method (lines 18-22). This method will display a message along with information provided by the user (i.e. the name of the relative and that person's relationship to the user).
Class ZombieTest
This class contains the Main method (lines 27-47), which is the entry point for any program.
First, I get user input. I create a local variable "nameOfRelative" (line 29) which captures the input for relative's name (lines 30-32) and likewise for local variable "relationToRelative" (line 36-38). (You'll see some extra Console.WriteLine() statements. Those are added just to provide some spacing between text to make the output more readable.)
Second, I create a new object (line 42). Since every class in C# is also a type, I just use the name of the class Zombie and call the object "survivor".
Here we do some major connecting of the dots.
I provide the local variables, nameOfRelative and relationToRelative as the arguments for the object creation expression (line 42). The object creation expression comes after the equals sign when a new object is created, like this: Zombie myZombie = new Zombie (nameOfRelative, relationToRelative). The part in bold is the object creation expression.
Then I call the method, DisplayInfo (line 43), which will display the name and relationship provided by the user. (Remember that you can't call a method in another class without first creating an object of that class, which I did with the Zombie object "survivor".)
That's all well and good, but just how does class Zombie know about these local variables and where they are supposed to be used? I think this part is where it gets really confusing. Let's break it down.
The constructor takes two arguments,"name" and "relationship", both of type string. Remember that these are the names of the constructor's parameters, not the actual values. The object creation expression's arguments are passed to the constructor and this is how the constructor's parameters get actual values. Since the properties are assigned the value of the constructor's parameters, the properties receive the values of the local variables declared in class ZombieTest. Then the method executes.
Recap
When a new object is created, the arguments provided to the the object creation expression are passed to the constructor's parameters. Because the properties are assigned the values in the constructor's parameters, they get those values. Then, the method, which uses the properties, is able to carry out its task.
In the post prior to this one, you will see code that includes class Zombie and class ZombieTest. Or get it here: https://github.com/htravar/Zombie. Don't let the fact there are two classes freak you out. Think of it this way - class Zombie contains the general instructions for what the program should do and class ZombieTest gives class Zombie specific data to carry out the program.
Class Zombie
The properties "Relations" and "RelativeName" (lines 9-10) are auto-implemented. This means that instead of writing out the private instance variables and the properties separately, we skip writing out the private instance variables and we skip writing out the get and set accessors. You know when you see auto-implemented properties that private instance variables of the same name have been created for you. (Note: There are times when you will want to add code to your accessors and you will not auto-implement. That is a topic for another day.)
Next we come to the constructor (lines 12-16), which you will recognize because it has a) the same name as the class, b) does not have a return type like method and c) it has parameters. If it did not have parameters, it would be a default constructor. A default constructor is provided by the compiler when you do not provide one yourself. The default values are null or 0. Here, I want to initialize the object with some values other than null or 0, so I have created my own constructor with parameters "name" and "relationship" (line 12), both of type string. For more info on constructors, see http://www.dotnetperls.com/constructor.
Now we connect the first two dots, the properties and the constructor. In the constructor, I use an assignment statement (line 14) to give the property "RelativeName" whatever value is passed to the constructor's parameter "name". Likewise for property "Relations" and the parameter "relationship" (line 15).
We'll come back to how we get the relative's name and relationship actually into the program. For now, we move on to the method (lines 18-22). This method will display a message along with information provided by the user (i.e. the name of the relative and that person's relationship to the user).
Class ZombieTest
This class contains the Main method (lines 27-47), which is the entry point for any program.
First, I get user input. I create a local variable "nameOfRelative" (line 29) which captures the input for relative's name (lines 30-32) and likewise for local variable "relationToRelative" (line 36-38). (You'll see some extra Console.WriteLine() statements. Those are added just to provide some spacing between text to make the output more readable.)
Second, I create a new object (line 42). Since every class in C# is also a type, I just use the name of the class Zombie and call the object "survivor".
Here we do some major connecting of the dots.
I provide the local variables, nameOfRelative and relationToRelative as the arguments for the object creation expression (line 42). The object creation expression comes after the equals sign when a new object is created, like this: Zombie myZombie = new Zombie (nameOfRelative, relationToRelative). The part in bold is the object creation expression.
Then I call the method, DisplayInfo (line 43), which will display the name and relationship provided by the user. (Remember that you can't call a method in another class without first creating an object of that class, which I did with the Zombie object "survivor".)
That's all well and good, but just how does class Zombie know about these local variables and where they are supposed to be used? I think this part is where it gets really confusing. Let's break it down.
The constructor takes two arguments,"name" and "relationship", both of type string. Remember that these are the names of the constructor's parameters, not the actual values. The object creation expression's arguments are passed to the constructor and this is how the constructor's parameters get actual values. Since the properties are assigned the value of the constructor's parameters, the properties receive the values of the local variables declared in class ZombieTest. Then the method executes.
Recap
When a new object is created, the arguments provided to the the object creation expression are passed to the constructor's parameters. Because the properties are assigned the values in the constructor's parameters, they get those values. Then, the method, which uses the properties, is able to carry out its task.
Code Sample for Construction Junction in C#
1 //created by Heather Travar on 4/1/14
2 //This program asks user who in their family is most likely to survive a zombie
3 //apocalypse and displays the results
4 //also get code here: https://github.com/htravar/Zombie
5 using System;
6
7 class Zombie
8 {
9 public string Relations {get; set;}//auto implemented properties
10 public string RelativeName {get; set;}
11
12 public Zombie(string name, string relationship)
13 {
14 RelativeName = name;
15 Relations = relationship;
16 }
17
18 public void DisplayInfo()
19 {
20 Console.WriteLine("The relative you feel most likely\nto survive a zombie");
21 Console.WriteLine ("apocalypse is {0}, your{1}.", RelativeName, Relations);
22 }
23 }//end class Zombie
24
25 class ZombieTest
26 {
27 static void Main(string[] args)
28 {
29 string nameOfRelative;
30 Console.WriteLine("Will anyone in your family survive the zombie apocalypse?");
31 Console.WriteLine("Enter the name of the one MOST likely to survive.");
32 nameOfRelative = Console.ReadLine();
33
34 Console.WriteLine();
35
36 string relationtoRelative;
37 Console.WriteLine("Enter this person's relationship to this you.");
38 relationtoRelative = Console.ReadLine();
39
40 Console.WriteLine();
41
42 Zombie survivor = new Zombie(nameOfRelative, relationtoRelative);
43 survivor.DisplayInfo();
44
45 Console.ReadKey();
46
47 }//end Main method
48 }//end class ZombieTest
2 //This program asks user who in their family is most likely to survive a zombie
3 //apocalypse and displays the results
4 //also get code here: https://github.com/htravar/Zombie
5 using System;
6
7 class Zombie
8 {
9 public string Relations {get; set;}//auto implemented properties
10 public string RelativeName {get; set;}
11
12 public Zombie(string name, string relationship)
13 {
14 RelativeName = name;
15 Relations = relationship;
16 }
17
18 public void DisplayInfo()
19 {
20 Console.WriteLine("The relative you feel most likely\nto survive a zombie");
21 Console.WriteLine ("apocalypse is {0}, your{1}.", RelativeName, Relations);
22 }
23 }//end class Zombie
24
25 class ZombieTest
26 {
27 static void Main(string[] args)
28 {
29 string nameOfRelative;
30 Console.WriteLine("Will anyone in your family survive the zombie apocalypse?");
31 Console.WriteLine("Enter the name of the one MOST likely to survive.");
32 nameOfRelative = Console.ReadLine();
33
34 Console.WriteLine();
35
36 string relationtoRelative;
37 Console.WriteLine("Enter this person's relationship to this you.");
38 relationtoRelative = Console.ReadLine();
39
40 Console.WriteLine();
41
42 Zombie survivor = new Zombie(nameOfRelative, relationtoRelative);
43 survivor.DisplayInfo();
44
45 Console.ReadKey();
46
47 }//end Main method
48 }//end class ZombieTest
Thursday, April 10, 2014
When did I begin to feel like a programmer?
Answer: Exercise 5.41, Chapter 5, Control Statements, Part I - Visual C# 2012 (Dietel).
Yes, that was my "a-ha" moment. It doesn't seem so pivotal, chapter 5. Here's why it was a turning point:
The encrypt/decrypt exercise. I wanted some extra practice after I finished my lab assignment, so I picked the last exercise in chapter 5 to do. See code here. (If you can't see the code, let me know. I am in the very beginning phase of learning GitHub.)
In the exercise, the user enters four digits, 0-9. Each digit is first encrypted and then the digits are swapped (first with third, second with fourth). That part was easy.
The second part of the exercise is the decryption part. At first, I was stuck. I assumed I need to concoct some complex math formula to break down the encryption, but everything I came up with failed to work in all scenarios. I assumed the failure was due to my very weak math background. It is rather anemic.
But then I saw the problem for what it really was - a programming problem. My failure was in addressing it as a mathematical problem. What I finally realized was that a good algorithm, utilizing components of math, yielded the correct results. The emphasis should have been on the algorithm and not some convoluted formula. I couldn't see the forest for the trees.
As you can see from the code, my solution was this:
First, add "1" to each encrypted digit to avoid having a negative number in the fourth step.
Second, subtract "7". This gave me the decrypted numbers, except that there would be some double digits. Third, swap the numbers back to their original places.
Fourth, use modulo (dividing by 10) to get rid of the first digit of the double digits (ex. 12 becomes 2) without losing the single digits (ex. 3/10 has a remainder of 3).
When I started law school, I recall the learning curve the first semester being practically vertical. But I worked hard to learn to think like a lawyer and the learning curve flattened out dramatically the second semester. By the time I started my second year, it was all routine.
I realize this encryption exercise is very simplistic, but it taught me an important lesson about troubleshooting. Sometimes, it's a matter of making sure you have the right logical perspective. While I have a long way to go before I can call myself a programmer with any confidence, chapter 5 helped me climb higher on the learning curve.
Subscribe to:
Posts (Atom)