Chapter 4: Writing, Debugging, and Testing Functions [Flashcarder]

1
Q

What is a fundamental principle of programming mentioned in the book?

A

Don’t Repeat Yourself (DRY).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

What should you do if you find yourself writing the same statements over and over again while programming?

A

Turn those statements into a function.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

How are functions described in the book?

A

Functions are like tiny programs that complete one small task, usually having inputs and outputs.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

What feature was introduced with C# 9 and is used by the default project template for console apps since C# 10 and .NET 6?

A

The top-level program feature.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

How do functions work with the automatically generated Program class and its <Main>$ method in top-level programs?

A

Functions defined in top-level programs become local functions within the <Main>$ method of the Program class.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

What is the suggested practice for the placement of functions in a file?

A

Functions should be placed at the bottom of the file rather than mixed with other top-level statements.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

What compiler error occurs if types like classes are declared in the middle of the Program.cs file?

A

Compiler error CS8803.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

What does the compiler automatically generate for a local function in C#?

A

The compiler generates an inner method within the existing method or function, making it local to that context.

If the local function is within the Main method of the Program class, it remains nested inside that method, without creating a new class or method.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Where must import statements (using) be placed in the Program.cs file?

A

Import statements must go at the top of the Program.cs file.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Where can statements that go into the <Main>$ function be placed in the Program.cs file?

A

Statements that will go in the <Main>$ function can be mixed with functions in the middle of the Program.cs file. Any functions will become local functions in the <Main>$ method.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Why can’t local functions have XML comments?

A

Local functions cannot have XML comments because they cannot be used outside the member in which they are declared.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

What is a better approach than defining functions within the Program.cs file?

A

A better approach is to write any functions in a separate file and define them as static members of the Program class.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

What should you name a new class file for defining functions as static members of the Program class?

A

The name of the file does not actually matter, but using a naming convention like Program.Functions.cs is sensible.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

What happens when you define a partial Program class with static functions in a separate file?

A

The compiler defines a Program class with a <Main>$ function and merges your function as a member of the Program class.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Why should you not define a namespace for your partial Program class?

A

If you define a namespace for your partial Program class, it will be in a different namespace and will not merge with the auto-generated partial Program class.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

What is the strict definition of a parameter in a function?

A

A parameter is a variable in a function definition.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

Provide an example of a function with a parameter.

A
void Hire(DateTime startDate) 
{
    // Function implementation.
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

What is the strict definition of an argument in a function call?

A

An argument is the data you pass into the method’s parameters when a method is called.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

Provide an example of passing an argument to a function.

A
DateTime when = new(year: 2024, month: 11, day: 5);
Hire(when);
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

How can you specify the parameter name when passing an argument?

A

You can specify the parameter name by using named arguments.
For example, MyMethod(paramName: value);

DateTime when = new(year: 2024, month: 11, day: 5);
Hire(startDate: when);
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

What terms do the official Microsoft documentation use interchangeably?

A

Named and optional arguments and
named and optional parameters.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q

How can a single object act as both a parameter and an argument?

A

Within a function implementation, a parameter can be passed as an argument to another function.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
23
Q

Provide an example where a parameter is passed as an argument to another function.

A
void Hire(DateTime startDate)
{
    ...
    SaveToDatabase(startDate, employeeRecord);
    ...
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
24
Q

What is a classic example of naming a parameter in C#?

A

The parameter named args in the Main function.

static void Main(String[] args)
{
    ...
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
25
Q

Summarize the difference between parameters and arguments.

A

Parameters define inputs to a function.

Arguments are passed to a function when calling the function.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
26
Q

What is a good practice when using the terms parameter and argument?

A

Try to use the correct term depending on the context, but do not get pedantic with other developers if they “misuse” a term.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
27
Q

What are cardinal numbers?

A

Cardinal numbers are numbers used to count, for example, 1, 2, and 3.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
28
Q

What are ordinal numbers?

A

Ordinal numbers are numbers used to order, for example, 1st, 2nd, and 3rd.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
29
Q

How is the factorial of a number calculated?

A

The factorial is calculated by multiplying the number by each of the positive integers less than it until reaching 1.
For example, the factorial of 5 is 5 x 4 x 3 x 2 x 1 = 120.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
30
Q

What is the factorial of 0?

A

0! = 1

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
31
Q

Provide the definition of a factorial for a positive integer n.

A

n! = n × (n − 1)!, for n ∈ { 1, 2, 3, … }

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
32
Q

How is a negative number handled in the Factorial function?

A

The function throws an ArgumentOutOfRangeException.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
33
Q

What value does the Factorial function return when the input is 0?

A

The function returns 1.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
34
Q

Provide the implementation of the Factorial function.

A
static int Factorial(int number)
{
    if (number < 0)
    {
        throw new ArgumentOutOfRangeException(message:
        $"The factorial function is defined for non-negative integers only. Input: {number}",
        paramName: nameof(number));
    }
    else if (number == 0)
    {
        return 1;
    }
    else
    {
        return number * Factorial(number - 1);
    }
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
35
Q

What is recursion in the context of the Factorial function?

A

Recursion is a technique where a function calls itself within its implementation.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
36
Q

What are some potential problems with recursion mentioned in the text?

A

Recursion can lead to problems such as stack overflow due to too many function calls because memory is used to store data on every function call.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
37
Q

What is an alternative to recursion that is mentioned as more practical in C#?

A

Iteration is a more practical solution than recursion in C#.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
38
Q

Why do factorials of 13 and higher overflow the int type?

A

Factorials of 13 and higher overflow the int type because they exceed the maximum positive value that can be stored in a 32-bit integer, which is about 2 billion.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
39
Q

How can you modify the Factorial function to check for overflows?

A

Use the checked keyword in the statement that calls itself:

checked
{
    return number * Factorial(number - 1);
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
40
Q

How can the RunFactorial function be modified to handle overflow and other exceptions?

A
static void RunFactorial()
{
    for (int i = -2; i <= 15; i++)
    {
        try
        {
            WriteLine($"{i}! = {Factorial(i):N0}");
        }
        catch (OverflowException)
        {
            WriteLine($"{i}! is too big for a 32-bit integer.");
        }
        catch (Exception ex)
        {
            WriteLine($"{i}! throws {ex.GetType()}: {ex.Message}");
        }
    }
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
41
Q

What is the output of the modified RunFactorial function for numbers -2 to 15?

A
-2! throws System.ArgumentOutOfRangeException: The factorial function is defined for non-negative integers only. Input: -2 (Parameter 'number')
-1! throws System.ArgumentOutOfRangeException: The factorial function is defined for non-negative integers only. Input: -1 (Parameter 'number')
0! = 1
1! = 1
2! = 2
...
12! = 479,001,600
13! is too big for a 32-bit integer.
14! is too big for a 32-bit integer.
15! is too big for a 32-bit integer.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
42
Q

What is shown by default when calling a function in a code editor?

A

A tooltip with basic information is shown by default.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
43
Q

How can you improve the tooltip information in Visual Studio Code?

A

1.Customize Tooltip Settings:
* Adjust font size and color for better readability in Settings > Editor: Tooltip Font Size and Editor: Tooltip Color.
* Enable or disable specific tooltips by searching for tooltip in the settings (Ctrl+,) and customizing preferences.

2.Install Extensions:
Use IntelliSense extensions like IntelliSense for CSS class names in HTML, Path Intellisense, and language-specific extensions to enhance the detail and relevance of tooltip information.

3.Use Settings Sync:
* Sync your customized settings across different devices using Visual Studio Code’s Settings Sync feature.

4.Edit Settings JSON:
* Manually tweak tooltip settings in settings.json for more precise control.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
44
Q

What happens when you type 3 forward slashes (///) above a function in Visual Studio?

A

It expands into an XML comment template.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
45
Q

What is the primary purpose of XML documentation comments?

A

To be used with tools that convert the comments into documentation, like Sandcastle.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
46
Q

Why don’t local functions support XML comments?

A

Because local functions cannot be used outside the member in which they are declared, making it unnecessary to generate documentation for them.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
47
Q

What is the recommended practice for adding XML documentation comments?

A

Add XML documentation comments to all your functions except local functions.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
48
Q

What is F#?

A

F# is Microsoft’s strongly typed functional-first programming language that compiles to Intermediate Language (IL) to be executed by .NET.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
49
Q

What are some important attributes of functional languages?

A

1.Modularity: Breaks up a large complex code base into smaller pieces.

2.Immutability: Variables do not exist in the traditional sense, reducing bugs.

3.Maintainability: Code is cleaner and clearer (for mathematically-inclined programmers).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
50
Q

What are some features added to C# to support a more functional approach?

A

Tuples and pattern matching in C# 7.

Non-null reference types in C# 8.

Improved pattern matching and adding records in C# 9.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
51
Q

What is an expression-bodied function member in C#?

A

A concise syntax for defining methods and properties using the => character to indicate a return value.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
52
Q

What is the Fibonacci sequence?

A

A sequence of numbers starting with 0 and 1, where each subsequent number is the sum of the previous two numbers.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
53
Q

Provide the implementation of the FibImperative function.

A
static int FibImperative(uint term)
{
    if (term == 0)
    {
        throw new ArgumentOutOfRangeException();
    }
    else if (term == 1)
    {
        return 0;
    }
    else if (term == 2)
    {
        return 1;
    }
    else
    {
        return FibImperative(term - 1) + FibImperative(term - 2);
    }
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
54
Q

What does the FibImperative function do?

A

It calculates the Fibonacci sequence in an imperative style, using if-else statements and recursion.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
55
Q

Provide the implementation of the RunFibImperative function.

A
static void RunFibImperative()
{
    for (uint i = 1; i <= 30; i++)
    {
        WriteLine("The {0} term of the Fibonacci sequence is {1:N0}.",
        arg0: CardinalToOrdinal(i),
        arg1: FibImperative(term: i));
    }
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
56
Q

What is the output of the RunFibImperative function for the first 5 terms of the Fibonacci sequence?

A
The 1st term of the Fibonacci sequence is 0.
The 2nd term of the Fibonacci sequence is 1.
The 3rd term of the Fibonacci sequence is 1.
The 4th term of the Fibonacci sequence is 2.
The 5th term of the Fibonacci sequence is 3.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
57
Q

Provide the implementation of the FibFunctional function.

A
static int FibFunctional(uint term) => term switch
{
    0 => throw new ArgumentOutOfRangeException(),
    1 => 0,
    2 => 1,
    _ => FibFunctional(term - 1) + FibFunctional(term - 2)
};
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
58
Q

What does the FibFunctional function do?

A

It calculates the Fibonacci sequence in a declarative style using a switch expression and recursion.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
59
Q

Provide the implementation of the RunFibFunctional function.

A
static void RunFibFunctional()
{
    for (uint i = 1; i <= 30; i++)
    {
        WriteLine("The {0} term of the Fibonacci sequence is {1:N0}.",
        arg0: CardinalToOrdinal(i),
        arg1: FibFunctional(term: i));
    }
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
60
Q

What will be the result of running the RunFibFunctional function?

A

The result will be the same as the RunFibImperative function, displaying the first 30 terms of the Fibonacci sequence.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
61
Q

What is the main difference between FibImperative and FibFunctional functions?

A

FibImperative is written in an imperative style using if-else statements,
while FibFunctional is written in a declarative style using a switch expression.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
62
Q

What type of code editor must you use to debug problems at development time?

A

You must use a code editor that has debugging tools, such as Visual Studio 2022 or Visual Studio Code.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
63
Q

What is a breakpoint?

A

A breakpoint is a marker set on a line of code where the debugger will pause execution, allowing you to inspect the program state and find bugs.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
64
Q

How do you set a breakpoint in Visual Studio Code?

A
  1. Click on the line where you want to set the breakpoint.
  2. Navigate to Run | Toggle Breakpoint or press F9.
  3. A red circle will appear in the margin bar to indicate the breakpoint.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
65
Q

How do you start debugging in Visual Studio Code?

A
  1. Navigate to View | Run, or click the Run and Debug icon, or press Ctrl + Shift + D.
  2. Click the Run and Debug button at the top of the RUN AND DEBUG window.
  3. Select the Debugging project.
  4. Visual Studio Code will start the console app and pause at the breakpoint.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
66
Q

What is break mode in Visual Studio Code?

A

Break mode is when the debugger pauses execution at a breakpoint, highlighting the next line to be executed in yellow, and allowing inspection of the program state.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
67
Q

What are some common buttons in the debugging toolbar?

A
  • Start/Continue/F5: Starts or continues running the project.
  • Hot Reload: Reloads compiled code changes without restarting the app.
  • Break All: Breaks into the next available line of code.
  • Stop Debugging/Stop/Shift + F5: Stops the debugging session.
  • Restart/Ctrl or Cmd + Shift + F5: Stops and restarts the program with the debugger attached.
  • Show Next Statement: Moves the cursor to the next statement to be executed.
  • Step Into/F11: Steps into the code statements.
  • Step Over/F10: Steps over the code statements.
  • Step Out/Shift + F11: Steps out of the current function.
  • Show Threads in Source: Examines and works with threads in the application.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
68
Q

What are some of the most useful debugging windows in Visual Studio and Visual Studio Code?

A
  • VARIABLES: Shows the name, value, and type of any local variables.
  • WATCH: Shows the value of variables and expressions that you manually enter.
  • CALL STACK: Shows the stack of function calls.
  • BREAKPOINTS: Shows all your breakpoints and allows finer control over them.
  • DEBUG CONSOLE or Immediate Window: Enables live interaction with your code.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
69
Q

How can you step into code using Visual Studio 2022 or Visual Studio Code?

A

Navigate to Run or Debug | Step Into, click on the Step Into button in the toolbar, or press F11.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
70
Q

What does the Step Over command do during debugging?

A

Step Over (F10) executes the next line of code, skipping over the method calls without stepping into them.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
71
Q

What is the difference between Step Into and Step Over ?

A

Step Into steps into the method to allow you to debug each line within it, while Step Over executes the entire method in one go.

72
Q

How do you add an expression to the WATCH window in Visual Studio or Visual Studio Code?

A

Select the expression in the code, right-click it, and select Add to Watch or Add Watch.

73
Q

How do you change the console to use the integrated terminal in Visual Studio Code?

A

Modify the launch.json file to change the console setting from internalConsole to integratedTerminal.

74
Q

How do you create a launch configuration for a .NET Core Console App in Visual Studio Code?

A
  1. Click the create a launch.json file link.
  2. Select C# for the debugger.
  3. Click the Add Configuration button.
  4. Select .NET: Launch .NET Core Console App.
  5. Modify the launch.json file with the correct settings.
75
Q

How do you set a conditional breakpoint in Visual Studio Code or Visual Studio 2022?

A

Right-click the breakpoint and choose Edit Breakpoint (Visual Studio Code) or Conditions (Visual Studio 2022), then enter the expression that must evaluate to true for the breakpoint to activate.

76
Q

What does the Hit Count option do for breakpoints?

A

Hit Count specifies the number of times the breakpoint must be hit before it activates.

77
Q

How can you interact with your code using the DEBUG CONSOLE or Immediate Window?

A

You can enter commands or expressions to interrogate the program state, such as evaluating the value of variables or performing calculations.

78
Q

What steps should you follow to debug a console app using Visual Studio Code?

A
  1. Set a breakpoint.
  2. Click the Run and Debug button.
  3. Select the Debugging project.
  4. Step through the code using Step Into (F11) or Step Over (F10).
  5. Fix any bugs and restart debugging.
79
Q

What is Hot Reload?

A

Hot Reload is a feature that allows a developer to apply changes to code while the app is running and immediately see the effect.
It is also known as Edit and Continue.

80
Q

How do you start a console app with Hot Reload using Visual Studio Code?

A

In the TERMINAL, start the console app using the dotnet watch command.

81
Q

What happens when you change the message in the console app and Hot Reload is active?

A

The change is applied after a couple of seconds without needing to restart the console app.

82
Q

How do you stop the console app running with Hot Reload?

A

Press Ctrl + C to stop it running.

83
Q

Why is it important to log events and data during runtime?

A

Because end users are notoriously bad at accurately describing what they were doing when an error occurred, making it difficult to reproduce and fix the problem without logs.

84
Q

What is a good practice mentioned for logging?

A

Add code throughout your application to log what is happening, especially when exceptions occur, so that you can review the logs and use them to trace and fix issues.

85
Q

What are some common third-party logging frameworks mentioned?

A
  • Apache log4net
  • NLog
  • Serilog
86
Q

What is the difference between the Debug and Trace classes in .NET?

A

The Debug class is used to add logging that gets written only during development.

The Trace class is used to add logging that gets written during both development and runtime.

87
Q

What is a trace listener in .NET?

A

A trace listener is a type that can be configured to write output anywhere you like when the WriteLine method is called.

88
Q

How do you write messages using Debug and Trace classes?

A
Debug.WriteLine("Debug says, I am watching!");
Trace.WriteLine("Trace says, I am watching!");
89
Q

Why should you enable AutoFlush only during debugging and not in production?

A

Enabling AutoFlush reduces performance because it calls the Flush method after every write.
This behavior is useful during debugging to see immediate results but should not be used in production.

90
Q

What happens when you run the release configuration of the console app with trace listeners configured?

A

Only the Trace messages will be written to the trace listeners.

91
Q

What happens when you run the debug configuration of the console app with trace listeners configured?

A

Both Debug and Trace messages will be written to the trace listeners.

92
Q

How can you add statements to flush and close any buffered trace listeners for Debug and Trace?

A
Debug.Close();
Trace.Close();
93
Q

How do you start the Instrumenting project with debugging in Visual Studio Code?

A

Enter the following command in the TERMINAL window:
dotnet run --configuration Debug

94
Q

What is the benefit of using Debug.WriteLine calls throughout your code?

A

They will be stripped out automatically when you build the release version of your application, ensuring they do not affect performance.

95
Q

What are the possible trace levels that can be set using a trace switch?

A
  • Off (0): Outputs nothing.
  • Error (1): Outputs only errors.
  • Warning (2): Outputs errors and warnings.
  • Info (3): Outputs errors, warnings, and information.
  • Verbose (4): Outputs all levels.
96
Q

How can you set the value of a trace switch?

A

The value of a trace switch can be set using a number or a corresponding word, for example, using the number 3 or the word “Info”.

97
Q

What does setting a trace switch to “Verbose” do?

A

It outputs all levels, including errors, warnings, information, and verbose messages.

98
Q

How do you add the Microsoft.Extensions.Configuration.Binder and Microsoft.Extensions.Configuration.Json NuGet packages to a project in Visual Studio Code?

A
dotnet add package Microsoft.Extensions.Configuration.Binder
dotnet add package Microsoft.Extensions.Configuration.Json
99
Q

What is the difference between dotnet add package and dotnet add reference commands?

A

dotnet add package adds a reference to a NuGet package to your project file, which will be downloaded during the build process.

dotnet add reference adds a project-to-project reference to your project file, and the referenced project will be compiled if needed during the build process.

100
Q

Why is it useful to have fine control over trace output?

A

It allows you to control the verbosity of the logging output, making it easier to debug and monitor applications without overwhelming the log files with unnecessary information.

101
Q

What should you do if you encounter unexpected issues with a NuGet package?

A

Try using an earlier version of the package.

102
Q

How do you define a setting named PacktSwitch with a value of Info in appsettings.json?

A
{
  "PacktSwitch": {
    "Value": "Info"
  }
}
103
Q

What configuration is needed to copy appsettings.json to the output directory in Visual Studio?

A

Set the Copy to Output Directory property of appsettings.json to Copy if newer or Copy always.

104
Q

Provide the project file element that ensures appsettings.json is copied to the output directory.

A
<ItemGroup>
  <None Update="appsettings.json">
    <CopyToOutputDirectory>Always</CopyToOutputDirectory>
  </None>
</ItemGroup>
105
Q

How do you output the 4 trace switch levels in C#?

A
Trace.WriteLineIf(ts.TraceError, "Trace error");
Trace.WriteLineIf(ts.TraceWarning, "Trace warning");
Trace.WriteLineIf(ts.TraceInfo, "Trace information");
Trace.WriteLineIf(ts.TraceVerbose, "Trace verbose");
106
Q

How do you ensure Debug and Trace are not closed prematurely in your code?

A

Do not close Debug or Trace before you are done using them. If you close them and then write to them, nothing will happen.

107
Q

How do you modify appsettings.json to set a level value of Warning?

A
{
  "PacktSwitch": {
    "Value": "2"
  }
}
108
Q

What is the purpose of logging the name of the source code file, the method, and the line number?

A

Logging this information helps in debugging by providing context about where a particular log entry was generated in the source code.

109
Q

What special attributes in C# can be used to get information about the method caller?

A
[CallerMemberName]
[CallerFilePath]
[CallerLineNumber]
[CallerArgumentExpression]
110
Q

What does the [CallerMemberName] attribute do?

A

It sets the string parameter to the name of the method or property that is executing the method that defines this parameter.

111
Q

What does the [CallerFilePath] attribute do?

A

It sets the string parameter to the name of the source code file that contains the statement that is executing the method that defines this parameter.

112
Q

What does the [CallerLineNumber] attribute do?

A

It sets the int parameter to the line number in the source code file of the statement that is executing the method that defines this parameter.

113
Q

What does the [CallerArgumentExpression] attribute do?

A

It sets the string parameter to the expression that has been passed to the parameter named in the attribute.

114
Q

How must these parameters with special attributes be defined?

A

They must be optional by assigning default values to them.

115
Q

Why is it important to find bugs early in the development process?

A

The earlier a bug is discovered, the less expensive it will be to fix.

116
Q

What is unit testing?

A

Unit testing tests a small unit of code, typically a method or function, in isolation from its dependencies.

117
Q

What is Test-Driven Development (TDD)?

A

TDD is a principle where programmers create unit tests before writing the code.

118
Q

What are the 3 unit testing frameworks mentioned?

A
  • MSTest
  • NUnit
  • xUnit.net
119
Q

What are integration tests?

A

Integration tests check if smaller units and larger components work together as a single piece of software, sometimes involving external components.

120
Q

What do system tests evaluate?

A

System tests evaluate the whole system environment in which the software will run.

121
Q

What is performance testing?

A

Performance testing measures how well the software performs, such as the response time for returning a web page full of data.

122
Q

What is load testing?

A

Load testing measures how many requests the software can handle simultaneously while maintaining required performance.

123
Q

What is user acceptance testing?

A

User acceptance testing evaluates if users can happily complete their work using the software.

124
Q

What should each unit test include?

A

Each unit should have multiple tests:
typical inputs and expected outputs, extreme input values to test boundaries, and deliberately wrong inputs to test exception handling.

125
Q

How do you create a new class library project named CalculatorLib using Visual Studio Code?

A
  • In TERMINAL, switch to the root folder.
  • Use the dotnet CLI to create the project: dotnet new classlib -o CalculatorLib.
  • Add the project folder to the solution: dotnet sln add CalculatorLib.
126
Q

How do you compile the CalculatorLib project in Visual Studio Code?

A

In a TERMINAL window for the CalculatorLib folder, enter the command: dotnet build

127
Q

How do you create a new xUnit Test Project named CalculatorLibUnitTests using Visual Studio Code?

A

In the root folder, enter the following commands:
~~~
dotnet new xunit -o CalculatorLibUnitTests
dotnet sln add CalculatorLibUnitTests
~~~

128
Q

How do you add a project reference to the CalculatorLib project in CalculatorLibUnitTests using Visual Studio Code?

A

Use the dotnet CLI command: dotnet add reference ..\CalculatorLib\CalculatorLib.csproj

129
Q

Provide the XML configuration to add a project reference to CalculatorLib in CalculatorLibUnitTests.csproj.

A
<ItemGroup>
  <ProjectReference Include="..\CalculatorLib\CalculatorLib.csproj" />
</ItemGroup>
130
Q

What are the 3 parts of a well-written unit test?

A
  1. Arrange: Declare and instantiate variables for input and output.
  2. Act: Execute the unit being tested.
  3. Assert: Make assertions about the output to verify the expected results.
131
Q

What is the purpose of the Arrange part in a unit test?

A

To set up the inputs and the unit under test by declaring and instantiating necessary variables.

132
Q

What is the purpose of the Act part in a unit test?

A

To execute the function or method that you want to test.

133
Q

What is the purpose of the Assert part in a unit test?

A

To compare the actual results with the expected results and verify the correctness of the code.

134
Q

Provide an example of a unit test method for adding 2 and 2 using xUnit.

A
[Fact]
public void TestAdding2And2()
{
    // Arrange
    double a = 2;
    double b = 2;
    double expected = 4;
    Calculator calc = new();
    
    // Act
    double actual = calc.Add(a, b);
    
    // Assert
    Assert.Equal(expected, actual);
}
135
Q

How do you run unit tests in Visual Studio Code?

A
  1. Navigate to View | Testing.
  2. In the TESTING window, expand the CalculatorLibUnitTests project.
  3. Hover over CalculatorUnitTests and click the Run Tests button (black triangle icon).
  4. Check the TEST RESULTS tab for the test results.
136
Q

What should you do if a unit test fails?

A

Fix the bug in the code, then run the unit tests again to ensure all tests pass.

137
Q

When should you catch and handle an exception in your code?

A

You should only catch and handle an exception if you have enough information to mitigate the issue.
Otherwise, allow the exception to pass up through the call stack to a higher level.

138
Q

What are usage errors in the context of exceptions?

A

Usage errors occur when a programmer misuses a function, typically by passing invalid values as parameters.
These errors should be fixed before production runtime.

139
Q

What are execution errors, and how do they differ from usage errors?

A

Execution errors occur at runtime and cannot be fixed by writing “better” code.

They include program errors, which can be fixed programmatically,
and system errors, which often cannot be fixed programmatically.

140
Q

What should you do if a parameter to a function should not be null?

A

Throw an ArgumentNullException.

141
Q

What exception should you throw if a parameter value is invalid for other reasons?

A

Throw an ArgumentException, NotSupportedException, or InvalidOperationException.

142
Q

What is a good practice if a function cannot successfully perform its operation?

A

Consider it a function failure and report it by throwing an exception.

143
Q

What are the 2 types of errors that execution errors can be split into?

A
  1. Program errors
  2. System errors
144
Q

What should you do if you attempt to access a network resource but the network is down?

A

Handle the system error by logging an exception and possibly backing off for a time and trying again.

145
Q

Why is it important to include a descriptive message when throwing an exception?

A

To help whoever will read it (typically a developer or end user) understand the problem.

146
Q

What are guard clauses in the context of exceptions?

A

Guard clauses are static methods on exception types used to validate parameters and throw exceptions if the values are invalid.

147
Q

What is the purpose of using guard clauses in functions?

A

To simplify the code by replacing if statements that throw new exceptions with static methods that perform the same validation and exception throwing.

148
Q

Provide an example of using guard clauses for parameter validation in a function.

A
static void Withdraw(string accountName, decimal amount)
{
    ArgumentException.ThrowIfNullOrWhiteSpace(accountName, paramName: nameof(accountName));
    ArgumentOutOfRangeException.ThrowIfNegativeOrZero(amount, paramName: nameof(amount));
    // process parameters
}
149
Q

What are some common guard clause methods for ArgumentException and ArgumentNullException?

A
  • ArgumentException: ThrowIfNullOrEmpty, ThrowIfNullOrWhiteSpace
  • ArgumentNullException: ThrowIfNull
150
Q

List some common guard clause methods for ArgumentOutOfRangeException.

A
  • ThrowIfEqual,
  • ThrowIfGreaterThan,
  • ThrowIfGreaterThanOrEqual,
  • ThrowIfLessThan,
  • ThrowIfLessThanOrEqual,
  • ThrowIfNegative,
  • ThrowIfNegativeOrZero,
  • ThrowIfNotEqual,
  • ThrowIfZero
151
Q

What is the entry point for a .NET console application?

A

The entry point is the Main method in the Program class, or <Main>$ if it was created by the top-level program feature.

152
Q

Explain the structure of a call stack in a .NET application.

A

The call stack is a sequence of method calls starting from the entry point (Main method) and includes all the methods that were called in sequence up to the current point of execution.

153
Q

What should you do if an exception is thrown in a function that does not have enough information to handle it?

A

Allow the exception to pass up through the call stack to a higher level where it can be appropriately handled.

154
Q

What happens if an exception is not caught by any function in the call stack?

A

The exception is automatically passed up the call stack until it reaches the top, where .NET outputs the exception details.

155
Q

Why is it a good practice to run code without the debugger attached unless needed for stepping through code?

A

Running without the debugger attached ensures that exceptions are output as they would be in a production environment, allowing you to see how they are handled.

156
Q

Where can programmers choose to catch an exception in their code?

A

Programmers can catch an exception near the failure point or higher up the call stack to simplify and standardize the code.

157
Q

What is the purpose of rethrowing an exception?

A

To catch an exception, log it, and then rethrow it so that higher-level code, which may have more information, can handle it appropriately.

158
Q

What are the 3 ways to rethrow an exception inside a catch block?

A
  • Using throw;: Rethrows the current exception, preserving the original stack trace. For example:
    catch (Exception ex)
    {
      // Some handling code
      throw;
    }
  • Using throw ex;: Rethrows the exception but resets the stack trace. For example:
    catch (Exception ex)
    {
      // Some handling code
      throw ex;
    }
  • Using throw new Exception(“message”, ex);: Wraps the original exception inside a new exception, preserving the original exception as the InnerException. For example:
    catch (Exception ex)
    {
      // Some handling code
      throw new Exception("An error occurred", ex);
    }
159
Q

Why is calling throw ex usually considered poor practice?

A

Because it loses some potentially useful information for debugging, specifically the original call stack.

160
Q

Provide an example of rethrowing an exception using all 3 techniques.

A
try
{
    Gamma();
}
catch (IOException ex)
{
    LogException(ex);
    // Throw the caught exception as if it happened here
    // this will lose the original call stack.
    throw ex;
    // Rethrow the caught exception and retain its original call stack.
    throw;
    // Throw a new exception with the caught exception nested within it.
    throw new InvalidOperationException(
        message: "Calculation had invalid values. See inner exception for why.",
        innerException: ex);
}
161
Q

What happens to the call stack details when you replace throw ex with throw in an exception handling block?

A

The output includes all the details of the call stack, retaining the original call stack information.

162
Q

What is the tester-doer pattern?

A

The tester-doer pattern uses pairs of functions: one to perform a test and the other to perform an action that would fail if the test was not passed.

163
Q

Why might the tester-doer pattern add performance overhead?

A

Because it involves performing an additional test before executing an action, which can be inefficient if done repeatedly.

164
Q

What problem can occur with the tester-doer pattern in a multi-threaded scenario?

A

A race condition can occur when one thread tests and another thread changes the state before the original thread proceeds, leading to incorrect assumptions about the state.

165
Q

What is the try pattern?

A

The try pattern combines the test and action parts into a single function, such as TryParse, to avoid the overhead and potential issues of the tester-doer pattern.

166
Q

What should you remember to do if your try pattern function fails?

A

Set the out parameter to the default value of its type and then return false.

167
Q

Why should the try pattern be preferred over the tester-doer pattern?

A

The try pattern avoids the performance overhead and potential race conditions associated with the tester-doer pattern.

168
Q

Exercise 4.1 – Test your knowledge

What does the C# keyword void mean?

A

The void keyword in C# indicates that a method does not return a value.
It is used when defining a method that performs an action but does not return any data.

169
Q

Exercise 4.1 – Test your knowledge

What are some differences between imperative and functional programming styles?

A

Imperative Programming:
* Focuses on how to perform tasks (step-by-step instructions).
* Uses statements that change a program’s state.
* Commonly uses loops, conditionals, and variable assignments.
* Examples: C#, Java, Python (in imperative style).

Functional Programming:
* Focuses on what to perform (expressions and declarations).
* Emphasizes immutability and pure functions (no side effects).
* Uses functions as first-class citizens and relies heavily on recursion.
* Examples: F#, Haskell, Scala, Lisp.

170
Q

Exercise 4.1 – Test your knowledge

In Visual Studio Code or Visual Studio, what is the difference between pressing F5, Ctrl or Cmd + F5, Shift + F5, and Ctrl or Cmd + Shift + F5?

A
  • F5: Starts debugging the application (Run with Debugging). If debugging is already active, it resumes execution.
  • Ctrl (Cmd) + F5: Starts the application without debugging (Run Without Debugging).
  • Shift + F5: Stops the current debugging session.
  • Ctrl (Cmd) + Shift + F5: Restarts the debugging session.
171
Q

Exercise 4.1 – Test your knowledge

Where does the Trace.WriteLine method write its output to?

A

The Trace.WriteLine method writes its output to trace listeners, which by default include the Output window in Visual Studio and any other listeners configured in the application’s configuration file.

172
Q

Exercise 4.1 – Test your knowledge

What are the 5 trace levels?

A
  1. Off: Turns off tracing.
  2. Error: Logs error messages.
  3. Warning: Logs warning messages.
  4. Info: Logs informational messages.
  5. Verbose: Logs all messages, including detailed tracing information.
173
Q

Exercise 4.1 – Test your knowledge

What is the difference between the Debug and Trace classes?

A

Debug Class:
* Used for debugging purposes.
* Writes output only in debug builds.
* Typically used with the #if DEBUG directive.
* Statements are removed in release builds.
* Example: Debug.WriteLine("Debug info");

Trace Class:
* Used for both debugging and production diagnostics.
* Writes output in both debug and release builds.
* Not removed in release builds.
* Example: Trace.WriteLine("Trace info");

174
Q

Exercise 4.1 – Test your knowledge

When writing a unit test, what are the 3 “A”s?

A
  1. Arrange: Set up the objects and prepare the prerequisites for the test.
  2. Act: Execute the method or functionality being tested.
  3. Assert: Verify that the outcome is as expected.
175
Q

Exercise 4.1 – Test your knowledge

When writing a unit test using xUnit, which attribute must you decorate the test methods with?

A

You must decorate the test methods with the [Fact] attribute in xUnit.

176
Q

Exercise 4.1 – Test your knowledge

What dotnet command executes xUnit tests?

A

The dotnet test command executes xUnit tests.

177
Q

Exercise 4.1 – Test your knowledge

What statement should you use to rethrow a caught exception named ex without losing the
stack trace?

A

You should use the throw; statement to rethrow a caught exception without losing the stack trace.