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.

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.






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

 

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.