From 61ce246ed35d98d739d46b8cd245a426359b0533 Mon Sep 17 00:00:00 2001 From: ipvg Date: Sat, 10 Aug 2024 23:44:42 -0400 Subject: [PATCH] avnc 028 --- 028_method_parameters/028_csharp.md | 559 ++++++++++++++++++ .../parameter_scope/Program.cs | 35 ++ .../parameter_scope/parameter_scope.csproj | 10 + 028_method_parameters/parameters/Program.cs | 29 + .../parameters/parameters.csproj | 10 + .../value_and_ref_params/Program.cs | 47 ++ .../value_and_ref_params.csproj | 10 + README.md | 1 + 8 files changed, 701 insertions(+) create mode 100644 028_method_parameters/028_csharp.md create mode 100644 028_method_parameters/parameter_scope/Program.cs create mode 100644 028_method_parameters/parameter_scope/parameter_scope.csproj create mode 100644 028_method_parameters/parameters/Program.cs create mode 100644 028_method_parameters/parameters/parameters.csproj create mode 100644 028_method_parameters/value_and_ref_params/Program.cs create mode 100644 028_method_parameters/value_and_ref_params/value_and_ref_params.csproj diff --git a/028_method_parameters/028_csharp.md b/028_method_parameters/028_csharp.md new file mode 100644 index 0000000..235dd26 --- /dev/null +++ b/028_method_parameters/028_csharp.md @@ -0,0 +1,559 @@ +# Create C# methods with parameters + +Learn how to use different types of input parameters in methods + +### Learning objectives + +- Learn more about using parameters + +- Understand method scope + +- Understand pass-by-reference and pass-by-value parameter types + +- Learn how to use optional and named arguments + +## Introduction + +Methods have the ability to perform operations on input. Passing parameters to +your methods allows you to perform the method's task with different input +values. Using method parameters lets you extend your code while keeping your +program organized and readable. If you consider a method to be a black box that +accepts input and performs a single task, you can quickly divide a large +problem into workable pieces. + +Suppose you need to write code that performs the same operation on different +sets of input. You might have three different arrays, and need to display the +contents of each one. You can create a `DisplayArray` method that accepts a +single array as input and displays the contents. Instead of writing code to +display each individual array, you can call the same method and provide the +different arrays as input. + +Parameters can make your methods more robust while still performing the same +general task. In this module, you'll learn more about working with parameters +and solidify your understanding of methods. + +### Learning Objectives + +In this module, you will: + +- Learn more about using parameters +- Understand method scope +- Understand pass-by-reference and pass-by-value parameter types +- Learn how to use optional and named arguments + +#### Prerequisites + +- Experience using C# data types including `int`, `string`, arrays, and 2D +arrays +- Experience using switch statements, if-else statements, and for-loops +- Experience using the `Random` class to generate a random number. +- Basic understanding of C# methods + +--- + +## Exercise + +### Use parameters in methods + +When creating methods, you'll often want to provide some information for the +method to use. Information consumed by a method is called a parameter. You can +supply as many parameters as needed to accomplish its task, or none at all. + +The terms 'parameter' and 'argument' are often used interchangeably. However, +'parameter' refers to the variable in the method signature. The 'argument' is +the value passed when the method is called. + +### Add parameters to methods + +Parameters in a method work similar to variables. A parameter is defined by +specifying the data type followed by the name of the parameter. Parameters are +declared in the method signature, and the values for the parameters are +provided by the method caller instead of being initialized inside the method +itself. Consider the following code: + +```cs + CountTo(5); + + void CountTo(int max) { + for (int i = 0; i < max; i++) { + Console.Write($"{i}, "); + } + } +``` + +In this example, the method `CountTo` accepts an integer parameter named `max`. +The parameter is referenced in the `for` loop of the method. When `CountTo` is +called, the integer 5 is supplied as an argument. + +In this exercise, you'll learn how to create and use your own method parameters. + +#### Create a method with parameters + +In this task, you'll create a method that adjusts scheduled times to a different +GMT time zone. The method should accept a list of times, the current time zone, +and the new time zone. Let's get started! + +Enter the following code into the code editor: + +```cs +int[] schedule = {800, 1200, 1600, 2000}; +``` + +To create a method with parameters, enter the following code on a new blank +line: + +```cs +void DisplayAdjustedTimes(int[] times, int currentGMT, int newGMT) { + +} +``` + +Notice that parameters are declared similar to the way you declare variables, +using the data type followed by the variable name. You can use parameters of +any data type, such as `string`, `bool`, `int`, `arrays`, and more! Multiple +parameters in a method are always comma separated. + +Enter the following code in the `DisplayAdjustedTimes` method: + +```cs +int diff = 0; +if (Math.Abs(newGMT) > 12 || Math.Abs(currentGMT) > 12) { + Console.WriteLine("Invalid GMT"); +} +``` + +Notice how you don't have to declare the variables `newGMT` and `currentGMT` +since they're already declared in the method signature. You also don't +initialize the variables since the method assumes the caller supplies those +arguments with assigned values. + +In this step, you create `int diff` to store the time difference and then check +to see that the provided GMT values are between -12 and 12. Using `Math.Abs` +gives you the absolute value of a number, so the GMT values are invalid if +they're greater than 12. + +To calculate the time difference, update the `DisplayAdjustedTimes` method as +follows: + +```cs +int diff = 0; +if (Math.Abs(newGMT) > 12 || Math.Abs(currentGMT) > 12) { + Console.WriteLine("Invalid GMT"); +} else if (newGMT <= 0 && currentGMT <= 0 || newGMT >= 0 && currentGMT >= 0) { + diff = 100 * (Math.Abs(newGMT) - Math.Abs(currentGMT)); +} else { + diff = 100 * (Math.Abs(newGMT) + Math.Abs(currentGMT)); +} +``` + +In this code, you check to see whether you need to add or subtract the absolute +values of the GMT time zones to get the difference in hours. If the GMT values +share the same sign (both positive or both negative), then the hours difference +is equal to the difference between the two numbers. If the GMT values have +opposite signs, then the difference is equal to the sum of the two numbers. +Since hours are represented in hundreds, you multiply the result by 100. + +To display the results, enter the following code at the end of the +`DisplayAdjustedTimes` method: + +```cs +for (int i = 0; i < times.Length; i++) { + int newTime = ((times[i] + diff)) % 2400; + Console.WriteLine($"{times[i]} -> {newTime}"); +} +``` + +To call your method, enter the following code after the `int[]` schedule +variable declaration: + +```cs +DisplayAdjustedTimes(schedule, 6, -6); +``` + +Notice that both variables and literals can be supplied as arguments to a +method. By using input parameters, the method isn't restricted to using the +values of global variables. + +### Check Your Work + +At the Terminal command prompt, enter `dotnet run` + +Verify that your code produces the following output: + +```txt +800 -> 2000 +1200 -> 0 +1600 -> 400 +2000 -> 800 +``` + +If your code displays different results, you'll need to review your code to +find your error and make updates. Run the code again to see if you've fixed the +problem. Continue updating and running your code until your code produces the expected results. + +- [Program.cs](./parameters/Program.cs) + +### Recap + +Here's what you've learned about parameters so far: + +- Information can be passed to methods in the form of parameters. +- Parameters are declared in the method signature. +- Multiple parameters are separated by commas. +- Methods can accept variable or literal arguments. + +--- + +## Exercise + +### Understand method scope + +`for` loops, `if-else` statements, and methods all represent different types of +code blocks. Each code block has its own 'scope'. 'Scope' is the region of a +program where certain data is accessible. Variables declared inside a method, +or any code block, are only accessible within that region. As programs become +more complicated, this pattern helps programmers consistently use clearly named +variables and maintain easy to read code. + +In this exercise, you'll learn more about method scope by working with +different types of methods and variables. + +#### Test variable scope + +Statements declared outside of any code block are called top-level statements. +Variables declared in top-level statements are called 'global variables'. Global +variables aren't restricted to any scope, and can be used anywhere throughout +the program. Global variables can be useful for different methods that need to +access the same data. However, it's important to pay attention to variable +names in different scopes. + +Enter the following code into the code editor: + +```cs +string[] students = {"Jenna", "Ayesha", "Carlos", "Viktor"}; + +DisplayStudents(students); +DisplayStudents(new string[] {"Robert","Vanya"}); + +void DisplayStudents(string[] students) { + foreach (string student in students) { + Console.Write($"{student}, "); + } + Console.WriteLine(); +} +``` + +In this code, you create a global `students` array, and a method +`DisplayStudents` that accepts a parameter with the same name. + +Save and run the code to observe the following output: + +```txt +Jenna, Ayesha, Carlos, Viktor, +Robert, Vanya, +``` + +Notice that the method parameter `student` takes precedence over the global +`student` array. It's important to be deliberate about what global variables you +want your methods to use. + +Delete the previous code. + +Enter the following code into the Editor: + +```cs +PrintCircleArea(12); + +void PrintCircleArea(int radius) { + double pi = 3.14159; + double area = pi * (radius * radius); + Console.WriteLine($"Area = {area}"); +} +``` + +This code calculates and displays the area of a circle. + +Attempt to reference the variables inside of the `PrintCircleArea` method by +updating your code as follows: + +```cs +PrintCircleArea(12); +double circumference = 2 * pi * radius; +``` + +Error messages appear informing you that the names `pi` and `radius` don't exist +in the current scope. Those variables only exist within the `PrintCircleArea` +method scope. + +Delete the incorrect code and add the following code: + +```cs +void PrintCircleCircumference(int radius) { + double pi = 3.14159; + double circumference = 2 * pi * radius; + Console.WriteLine($"Circumference = {circumference}"); +} +``` + +Since the variable `pi` is set to the same fixed value and used in both methods, +this value is a good candidate for a global variable. In this example, `radius` +isn't a global variable so that you can call the methods with different values +of `radius` without updating a variable each time. + +Update your code to the following: + +```cs +double pi = 3.14159; + +void PrintCircleArea(int radius) { + double area = pi * (radius * radius); + Console.WriteLine($"Area = {area}"); +} + +void PrintCircleCircumference(int radius) { + double circumference = 2 * pi * radius; + Console.WriteLine($"Circumference = {circumference}"); +} +``` + +Now both methods can reference the same value of `pi` without needing to define +it. You might have already guessed that methods can call other methods. +Generally, as long as a method is defined within the scope of your program, it +can be called anywhere. + +Add a new method to your code as follows: + +```cs +double pi = 3.14159; +PrintCircleInfo(12); +PrintCircleInfo(24); + +void PrintCircleInfo(int radius) { + Console.WriteLine($"Circle with radius {radius}"); + PrintCircleArea(radius); + PrintCircleCircumference(radius); +} +``` + +In this code, you create a new method `PrintCircleInfo` to call the existing +methods. The value of `radius` is also passed down to each method. Creating +modularized methods can help keep your code organized and easy to read. + +Save and run the code to observe the following output: + +```txt +Circle with radius 12 +Area = 452.38896 +Circumference = 75.39815999999999 +Circle with radius 24 +Area = 1809.55584 +Circumference = 150.79631999999998 +``` + +- [Program.cs](./parameter_scope/Program.cs) + +### Recap + +Here's what you've learned about method scope so far: + +Variables declared inside of a method are only accessible to that method. +Variables declared in top-level statements are accessible throughout the program. +Methods don't have access to variables defined within different methods. +Methods can call other methods. + +--- + +## Exercise + +### Use value and reference type parameters + +In C#, variables can be categorized into two main types, value types and +reference types. These types describe how variables store their values. + +Value types such as `int`, `bool`, `float`, `double`, and `char` directly +contain values. Reference types such as `string`, `array`, and objects (such as +instances of `Random`) don't store their values directly. Instead, reference +types store an address where their value is being stored. + +### Parameters passed by value and passed by reference + +When an argument is passed to a method, *value* type variables have their +values copied into the method. Each variable has its own copy of the value, so +the original variable isn't modified. + +With reference types, the address of the value is passed into the method. The +variable given to the method references the value at that address, so +operations on that variable affect the value that is referenced by the other. + +> Note +> It is important to remember that `string` is a reference type, but it is +immutable. That means once it has been assigned a value, it can't be altered. +In C#, when methods and operators are used to modify a string, the result that +is returned is actually a new string object. + +In this exercise, you'll learn more about passing reference and value type +arguments into methods. + +#### Test pass by value + +Enter the following code into the code editor: + +```cs +int a = 3; +int b = 4; +int c = 0; + +Multiply(a, b, c); +Console.WriteLine($"global statement: {a} x {b} = {c}"); + +void Multiply(int a, int b, int c) { + c = a * b; + Console.WriteLine($"inside Multiply method: {a} x {b} = {c}"); +} +``` + +The variables `a`, `b`, and `c` are passed to the `Multiply` method. The values +of the variables are printed during the method execution, and printed again +after the method is complete. + +Integers are value types, which have their values copied when passed into +methods. What do you think the output of `c` will be? + +Save and run your code to observe the following output: + +```cs +inside Multiply method: 3 x 4 = 12 +global statement: 3 x 4 = 0 +``` + +Notice that the value of `c` is only altered within the `Multiply` method. +Outside of the method, `c` retains its original value. + +#### Test pass by reference + +Enter the following code into the code editor: + +```cs +int[] array = {1, 2, 3, 4, 5}; + +PrintArray(array); +Clear(array); +PrintArray(array); + +void PrintArray(int[] array) { + foreach (int a in array) { + Console.Write($"{a} "); + } + Console.WriteLine(); +} + +void Clear(int[] array) { + for (int i = 0; i < array.Length; i++) { + array[i] = 0; + } +} +``` + +The code begins with `array` initialized to contain some integer values. The +values are displayed using the `PrintArray` method. The `Clear` method is called +on the array, and then the array is printed again. + +Arrays are reference types. Reference types store the address of their values +in memory. What do you think the output will be? + +Save and run your code to observe the following output: + +```txt +1 2 3 4 5 +0 0 0 0 0 +``` + +Notice that the array remains altered outside of the `Clear` method scope. This +happens because the `Clear` method updated the values stored at each address. + +#### Test with strings + +Earlier, you learned that strings are an *immutable* type. Even though a string +is a reference type, unlike an array, its value can't be altered once it's +assigned. You might have noticed this if you've used methods such as +`string.Replace` or `string.ToUpper`. In this task, you'll learn to correct a +common error found when working with strings. + +Enter the following code into the code editor: + +```cs +string status = "Healthy"; + +Console.WriteLine($"Start: {status}"); +SetHealth(status, false); +Console.WriteLine($"End: {status}"); + +void SetHealth(string status, bool isHealthy) { + status = (isHealthy ? "Healthy" : "Unhealthy"); + Console.WriteLine($"Middle: {status}"); +} +``` + +Save and run your code to observe the following output: + +```txt +Start: Healthy +Middle: Unhealthy +End: Healthy +``` + +If the `SetHealth` method didn't output the status, you might have assumed the +method didn't execute correctly. Instead, a new string with the value +"Unhealthy" was created and then lost in the method scope. + +To correct this problem, you can change `SetHealth` to use the global status +variable instead. + +Update your code as follows: + +```cs +string status = "Healthy"; + +Console.WriteLine($"Start: {status}"); +SetHealth(false); +Console.WriteLine($"End: {status}"); + +void SetHealth(bool isHealthy) { + status = (isHealthy ? "Healthy" : "Unhealthy"); + Console.WriteLine($"Middle: {status}"); +} +``` + +In this code, you overwrite the global `status` variable with the new string +value. + +Save and run your code to observe the following output: + +```txt +Start: Healthy +Middle: Unhealthy +End: Unhealthy +``` + +Now the updated string is captured and stored correctly. + +- [Program.cs](./value_and_ref_params/Program.cs) + +### Recap + +Here's what you've learned about value type and reference type parameters so +far: + +- Variables can be categorized as value types and reference types. +- Value types directly contain values, and reference types store the address of +the value. +- Methods using value type arguments create their own copy of the values. +- Methods that perform changes on an array parameter affect the original input +array. +- String is an immutable reference type. +- Methods that perform changes on a string parameter don't affect the original +string. + +--- + +## diff --git a/028_method_parameters/parameter_scope/Program.cs b/028_method_parameters/parameter_scope/Program.cs new file mode 100644 index 0000000..342071b --- /dev/null +++ b/028_method_parameters/parameter_scope/Program.cs @@ -0,0 +1,35 @@ +string[] students = {"Jenna", "Ayesha", "Carlos", "Viktor"}; + +display_students(students); +display_students(new string[] {"Robert","Vanya"}); + +void display_students(string[] students) { + foreach (string student in students) { + Console.Write($"{student}, "); + } + Console.WriteLine(); +} + +Console.WriteLine(); + +void print_circle_area(int radius) { + double area = Math.PI * (radius * radius); + Console.WriteLine($"Area = {area:F2}"); +} + +void print_circle_circumference(int radius) { + double circumference = 2 * Math.PI * radius; + Console.WriteLine($"Circumference = {circumference:F2}"); +} + +void print_circle_info(int radius){ + Console.WriteLine($"Circle with radius {radius}"); + print_circle_area(radius); + print_circle_circumference(radius); + Console.WriteLine(); +} + +//print_circle_area(12); +//print_circle_circumference(12); +print_circle_info(12); +print_circle_info(24); diff --git a/028_method_parameters/parameter_scope/parameter_scope.csproj b/028_method_parameters/parameter_scope/parameter_scope.csproj new file mode 100644 index 0000000..2150e37 --- /dev/null +++ b/028_method_parameters/parameter_scope/parameter_scope.csproj @@ -0,0 +1,10 @@ + + + + Exe + net8.0 + enable + enable + + + diff --git a/028_method_parameters/parameters/Program.cs b/028_method_parameters/parameters/Program.cs new file mode 100644 index 0000000..873c44c --- /dev/null +++ b/028_method_parameters/parameters/Program.cs @@ -0,0 +1,29 @@ +count_to(5); + +void count_to(int max) { + for (int i = 0; i < max; i++) { + Console.Write($"{i}, "); + } +} + +int[] schedule = {800, 1200, 1600, 2000}; + +void display_adjusted_times(int[] times, int current_GMT, int new_GMT) { + int diff = 0; + if (Math.Abs(new_GMT) > 12 || Math.Abs(current_GMT) > 12){ + Console.WriteLine("Invalid GMT"); + } else if ( + new_GMT <= 0 && current_GMT <= 0 || + new_GMT >= 0 && current_GMT >= 0 + ){ + diff = 100 * (Math.Abs(new_GMT) - Math.Abs(current_GMT)); + } else { + diff = 100 * (Math.Abs(new_GMT) + Math.Abs(current_GMT)); + } + for (int i=0; i {new_time}"); + } +} + +display_adjusted_times(schedule, 6, -6); diff --git a/028_method_parameters/parameters/parameters.csproj b/028_method_parameters/parameters/parameters.csproj new file mode 100644 index 0000000..2150e37 --- /dev/null +++ b/028_method_parameters/parameters/parameters.csproj @@ -0,0 +1,10 @@ + + + + Exe + net8.0 + enable + enable + + + diff --git a/028_method_parameters/value_and_ref_params/Program.cs b/028_method_parameters/value_and_ref_params/Program.cs new file mode 100644 index 0000000..5983ba9 --- /dev/null +++ b/028_method_parameters/value_and_ref_params/Program.cs @@ -0,0 +1,47 @@ +int a = 3; +int b = 4; +int c = 0; + +Multiply(a, b, c); +Console.WriteLine($"global statement: {a} x {b} = {c}"); + +void Multiply(int a, int b, int c) { + c = a * b; + Console.WriteLine($"inside Multiply method: {a} x {b} = {c}"); +} + +Console.WriteLine("--------------------------------"); + +int[] array = {1, 2, 3, 4, 5}; + +PrintArray(array); +Clear(array); +PrintArray(array); + +void PrintArray(int[] array) { + foreach (int a in array) { + Console.Write($"{a} "); + } + Console.WriteLine(); +} + +void Clear(int[] array) { + for (int i = 0; i < array.Length; i++) { + array[i] = 0; + } +} + +Console.WriteLine("--------------------------------"); + +string status = "Healthy"; + +Console.WriteLine($"Start: {status}"); +//SetHealth(status, false); +SetHealth(false); +Console.WriteLine($"End: {status}"); + +//void SetHealth(string status, bool isHealthy) { +void SetHealth(bool isHealthy) { + status = (isHealthy ? "Healthy" : "Unhealthy"); + Console.WriteLine($"Middle: {status}"); +} diff --git a/028_method_parameters/value_and_ref_params/value_and_ref_params.csproj b/028_method_parameters/value_and_ref_params/value_and_ref_params.csproj new file mode 100644 index 0000000..2150e37 --- /dev/null +++ b/028_method_parameters/value_and_ref_params/value_and_ref_params.csproj @@ -0,0 +1,10 @@ + + + + Exe + net8.0 + enable + enable + + + diff --git a/README.md b/README.md index 6761ca7..039ad34 100644 --- a/README.md +++ b/README.md @@ -32,3 +32,4 @@ Following 25. [Work with variable data](./025_Work_with_variable_data/025_csharp.md) 26. [Challenge - variable data](./026_Challenge_variable_data/026_csharp.md) 27. [Create methods](./027_create_methods/027_csharp.md) +28. [Methods with parameters](./028_method_parameters/028_csharp.md)