โ๏ธ ๐ก๐๐น๐น ๐๐ผ๐ฎ๐น๐ฒ๐๐ฐ๐ถ๐ป๐ด ๐ข๐ฝ๐ฒ๐ฟ๐ฎ๐๐ผ๐ฟ
โ The ๐ก๐๐น๐น ๐๐ผ๐ฎ๐น๐ฒ๐๐ฐ๐ถ๐ป๐ด ๐ข๐ฝ๐ฒ๐ฟ๐ฎ๐๐ผ๐ฟ (??) in C# is used to provide a concise way of handling null values. It's particularly useful when you want to provide a default value when a nullable expression evaluates to null. This operator helps make your code cleaner by reducing the need for verbose null checks and conditional statements.
  โ The ๐ก๐๐น๐น ๐๐ผ๐ฎ๐น๐ฒ๐๐ฐ๐ถ๐ป๐ด ๐ข๐ฝ๐ฒ๐ฟ๐ฎ๐๐ผ๐ฟ (??) in C# is used to provide a concise way of handling null values. It's particularly useful when you want to provide a default value when a nullable expression evaluates to null. This operator helps make your code cleaner by reducing the need for verbose null checks and conditional statements.
๐ ๐๐น๐ฒ๐ฎ๐ป ๐๐ผ๐ฑ๐ฒ
โ๏ธ ๐ก๐๐น๐น ๐๐ผ๐ฎ๐น๐ฒ๐๐ฐ๐ถ๐ป๐ด ๐ข๐ฝ๐ฒ๐ฟ๐ฎ๐๐ผ๐ฟ
โ The ๐ก๐๐น๐น ๐๐ผ๐ฎ๐น๐ฒ๐๐ฐ๐ถ๐ป๐ด ๐ข๐ฝ๐ฒ๐ฟ๐ฎ๐๐ผ๐ฟ (??) in C# is used to provide a concise way of handling null values. It's particularly useful when you want to provide a default value when a nullable expression evaluates to null. This operator helps make your code cleaner by reducing the need for verbose null checks and conditional statements.
๐ฅ ๐๐ฑ๐๐ฎ๐ป๐๐ฎ๐ด๐ฒ๐ ๐ผ๐ณ ๐๐๐ถ๐ป๐ด ๐๐ต๐ฒ ๐ป๐๐น๐น ๐ฐ๐ผ๐ฎ๐น๐ฒ๐๐ฐ๐ถ๐ป๐ด ๐ผ๐ฝ๐ฒ๐ฟ๐ฎ๐๐ผ๐ฟ:
โพ๏ธ ๐๐ผ๐ป๐ฐ๐ถ๐๐ฒ ๐๐ผ๐ฑ๐ฒ: It reduces the need for writing lengthy null-checking code, resulting in more compact and clear expressions.
โพ๏ธ ๐ฅ๐ฒ๐ฎ๐ฑ๐ฎ๐ฏ๐ถ๐น๐ถ๐๐: The operator is well-known among C# developers, so it improves the readability of your code by providing a common and recognizable pattern.
โพ๏ธ ๐๐๐ผ๐ถ๐ฑ๐ถ๐ป๐ด ๐๐๐ฝ๐น๐ถ๐ฐ๐ฎ๐๐ถ๐ผ๐ป: It eliminates the need to repeat the same null-checking logic throughout your codebase.
โพ๏ธ ๐๐ฒ๐ณ๐ฎ๐๐น๐ ๐ฉ๐ฎ๐น๐๐ฒ๐: It's particularly useful when you want to provide default values for nullable variables.
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐
  โ๏ธ ๐ก๐๐น๐น ๐๐ผ๐ฎ๐น๐ฒ๐๐ฐ๐ถ๐ป๐ด ๐ข๐ฝ๐ฒ๐ฟ๐ฎ๐๐ผ๐ฟ
โ The ๐ก๐๐น๐น ๐๐ผ๐ฎ๐น๐ฒ๐๐ฐ๐ถ๐ป๐ด ๐ข๐ฝ๐ฒ๐ฟ๐ฎ๐๐ผ๐ฟ (??) in C# is used to provide a concise way of handling null values. It's particularly useful when you want to provide a default value when a nullable expression evaluates to null. This operator helps make your code cleaner by reducing the need for verbose null checks and conditional statements.
๐ฅ ๐๐ฑ๐๐ฎ๐ป๐๐ฎ๐ด๐ฒ๐ ๐ผ๐ณ ๐๐๐ถ๐ป๐ด ๐๐ต๐ฒ ๐ป๐๐น๐น ๐ฐ๐ผ๐ฎ๐น๐ฒ๐๐ฐ๐ถ๐ป๐ด ๐ผ๐ฝ๐ฒ๐ฟ๐ฎ๐๐ผ๐ฟ:
โพ๏ธ ๐๐ผ๐ป๐ฐ๐ถ๐๐ฒ ๐๐ผ๐ฑ๐ฒ: It reduces the need for writing lengthy null-checking code, resulting in more compact and clear expressions.
โพ๏ธ ๐ฅ๐ฒ๐ฎ๐ฑ๐ฎ๐ฏ๐ถ๐น๐ถ๐๐: The operator is well-known among C# developers, so it improves the readability of your code by providing a common and recognizable pattern.
โพ๏ธ ๐๐๐ผ๐ถ๐ฑ๐ถ๐ป๐ด ๐๐๐ฝ๐น๐ถ๐ฐ๐ฎ๐๐ถ๐ผ๐ป: It eliminates the need to repeat the same null-checking logic throughout your codebase.
โพ๏ธ ๐๐ฒ๐ณ๐ฎ๐๐น๐ ๐ฉ๐ฎ๐น๐๐ฒ๐: It's particularly useful when you want to provide default values for nullable variables.
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐
โ๏ธ ๐ฅ๐ฒ๐๐ต๐ฟ๐ผ๐๐ถ๐ป๐ด ๐๐
๐ฐ๐ฒ๐ฝ๐๐ถ๐ผ๐ป๐
โ Exceptions should not be explicitly rethrown because it can lead to loss of information about the original exception. When an exception is thrown, it creates a stack trace that records the call stack at the point where the exception was thrown. This stack trace can be helpful for debugging the exception.
โ The preferred way to handle an exception is to catch it and then take some action to resolve the problem. This could involve logging the exception, displaying an error message to the user, or taking some other corrective action. If the exception cannot be resolved, it should be rethrown, but without specifying the exception explicitly. This will preserve the original stack trace information and make debugging easier.
๐ก When you want to wrap the exception in a different exception type. In this case, you should create a new exception object and then throw that object. Do not simply rethrow the original exception object.
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐
  โ Exceptions should not be explicitly rethrown because it can lead to loss of information about the original exception. When an exception is thrown, it creates a stack trace that records the call stack at the point where the exception was thrown. This stack trace can be helpful for debugging the exception.
โ The preferred way to handle an exception is to catch it and then take some action to resolve the problem. This could involve logging the exception, displaying an error message to the user, or taking some other corrective action. If the exception cannot be resolved, it should be rethrown, but without specifying the exception explicitly. This will preserve the original stack trace information and make debugging easier.
๐ก When you want to wrap the exception in a different exception type. In this case, you should create a new exception object and then throw that object. Do not simply rethrow the original exception object.
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐
โ๏ธ๐ฆ๐๐ถ๐๐ฐ๐ต ๐๐
๐ฝ๐ฟ๐ฒ๐๐๐ถ๐ผ๐ป
๐ฏ The ๐๐๐ถ๐๐ฐ๐ต ๐๐๐ฎ๐๐ฒ๐บ๐ฒ๐ป๐ has been part of C# since its early versions. It allows you to evaluate an expression against a series of case values and execute code blocks based on the matched case.
Each case value must be a constant value that is known at compile-time. After a case block is executed, you usually need to include a break statement to exit the switch statement.
๐ก The ๐๐๐ถ๐๐ฐ๐ต ๐ฒ๐ ๐ฝ๐ฟ๐ฒ๐๐๐ถ๐ผ๐ป was introduced in C# 8 as a more concise and expressive alternative to the traditional switch statement. It allows you to assign a value to a variable based on the value of an expression.
In a switch expression, you use the => syntax to specify the value to assign if the expression matches a certain case. The _ is a discard symbol and is used as the "default" case.
โ Both the ๐๐๐ถ๐๐ฐ๐ต ๐๐๐ฎ๐๐ฒ๐บ๐ฒ๐ป๐ and the ๐๐๐ถ๐๐ฐ๐ต ๐ฒ๐ ๐ฝ๐ฟ๐ฒ๐๐๐ถ๐ผ๐ป are used for similar purposes, the switch expression offers more concise syntax and greater flexibility for pattern matching and value assignment, making it a more powerful tool for modern C# development.
๐ค Which one do you prefer?
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐
  ๐ฏ The ๐๐๐ถ๐๐ฐ๐ต ๐๐๐ฎ๐๐ฒ๐บ๐ฒ๐ป๐ has been part of C# since its early versions. It allows you to evaluate an expression against a series of case values and execute code blocks based on the matched case.
Each case value must be a constant value that is known at compile-time. After a case block is executed, you usually need to include a break statement to exit the switch statement.
๐ก The ๐๐๐ถ๐๐ฐ๐ต ๐ฒ๐ ๐ฝ๐ฟ๐ฒ๐๐๐ถ๐ผ๐ป was introduced in C# 8 as a more concise and expressive alternative to the traditional switch statement. It allows you to assign a value to a variable based on the value of an expression.
In a switch expression, you use the => syntax to specify the value to assign if the expression matches a certain case. The _ is a discard symbol and is used as the "default" case.
โ Both the ๐๐๐ถ๐๐ฐ๐ต ๐๐๐ฎ๐๐ฒ๐บ๐ฒ๐ป๐ and the ๐๐๐ถ๐๐ฐ๐ต ๐ฒ๐ ๐ฝ๐ฟ๐ฒ๐๐๐ถ๐ผ๐ป are used for similar purposes, the switch expression offers more concise syntax and greater flexibility for pattern matching and value assignment, making it a more powerful tool for modern C# development.
๐ค Which one do you prefer?
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐
โ๏ธ One Dot Per Line
โ "One dot per line" is a principle of writing clean code in C# (and other programming languages) that suggests breaking chained method calls and property accesses onto separate lines, placing each dot on a new line. This helps to enhance code readability and maintainability by making the code structure clear and easier to follow.
โ Advantages of using "One dot per line" approach:
- Improved Readability: By placing each dot on a separate line, the code becomes more readable, especially when dealing with long chains of method calls or nested property access.
- Reduced Horizontal Scrolling: Code lines become shorter, reducing the need for horizontal scrolling while reading the code, which is often considered less pleasant and harder to follow.
- Easier Debugging: With each method call or property access on a separate line, it becomes easier to set breakpoints and debug specific parts of the code.
- Easier Code Review: The code becomes more structured, making it easier for colleagues to review and provide feedback on the code.
โ The "One dot per line" rule is a useful coding practice that can help to improve the readability, maintainability, and overall quality of your code.
Thank you for reading ๐
  โ "One dot per line" is a principle of writing clean code in C# (and other programming languages) that suggests breaking chained method calls and property accesses onto separate lines, placing each dot on a new line. This helps to enhance code readability and maintainability by making the code structure clear and easier to follow.
โ Advantages of using "One dot per line" approach:
- Improved Readability: By placing each dot on a separate line, the code becomes more readable, especially when dealing with long chains of method calls or nested property access.
- Reduced Horizontal Scrolling: Code lines become shorter, reducing the need for horizontal scrolling while reading the code, which is often considered less pleasant and harder to follow.
- Easier Debugging: With each method call or property access on a separate line, it becomes easier to set breakpoints and debug specific parts of the code.
- Easier Code Review: The code becomes more structured, making it easier for colleagues to review and provide feedback on the code.
โ The "One dot per line" rule is a useful coding practice that can help to improve the readability, maintainability, and overall quality of your code.
Thank you for reading ๐
โ๏ธ C#: Exceptions should not be thrown in finally blocks
โณ๏ธIf an exception is already being thrown within the try block or caught in a catch block, throwing another exception in the finally block will override the original exception. This means that the original exceptionโs message and stack trace will be lost, potentially making it challenging to diagnose and troubleshoot the root cause of the problem.
โณ๏ธHere are a few reasons why throwing exceptions from finally blocks is discouraged:
- Masking the original exception: If an exception is thrown in a finally block, it can overwrite the original exception that caused the try block to exit. This can make it harder to debug the actual cause of the problem, as you won't have access to the original exception information.
- Unpredictable behavior: When an exception is thrown from a finally block, it may interfere with the exception handling mechanism itself. For example, if the catch block outside the finally block handles the exception, throwing another exception from finally will disrupt the expected control flow.
- Resource leaks: The primary purpose of a finally block is to release resources or perform cleanup tasks. If an exception is thrown from the finally block, these cleanup operations may not be completed, leading to resource leaks or inconsistent program state.
โณ๏ธInstead of throwing exceptions from finally blocks, it's better to handle exceptions appropriately within the try, catch, and finally blocks. If an exception occurs in the finally block, it's usually best to log the error or take some alternative action to ensure proper cleanup without disrupting the main exception handling flow.
Thank you for reading ๐
  โณ๏ธIf an exception is already being thrown within the try block or caught in a catch block, throwing another exception in the finally block will override the original exception. This means that the original exceptionโs message and stack trace will be lost, potentially making it challenging to diagnose and troubleshoot the root cause of the problem.
โณ๏ธHere are a few reasons why throwing exceptions from finally blocks is discouraged:
- Masking the original exception: If an exception is thrown in a finally block, it can overwrite the original exception that caused the try block to exit. This can make it harder to debug the actual cause of the problem, as you won't have access to the original exception information.
- Unpredictable behavior: When an exception is thrown from a finally block, it may interfere with the exception handling mechanism itself. For example, if the catch block outside the finally block handles the exception, throwing another exception from finally will disrupt the expected control flow.
- Resource leaks: The primary purpose of a finally block is to release resources or perform cleanup tasks. If an exception is thrown from the finally block, these cleanup operations may not be completed, leading to resource leaks or inconsistent program state.
โณ๏ธInstead of throwing exceptions from finally blocks, it's better to handle exceptions appropriately within the try, catch, and finally blocks. If an exception occurs in the finally block, it's usually best to log the error or take some alternative action to ensure proper cleanup without disrupting the main exception handling flow.
Thank you for reading ๐
โ๏ธ C#: Replace if statement with Null Conditional Operator
โณ๏ธThe null conditional operator, also known as the null propagation operator or the safe navigation operator, is a feature introduced in C# 6.0 that allows you to write cleaner and more concise code when dealing with potentially null reference types.
โณ๏ธThe null conditional operator is represented by a question mark followed by a period (?.) and is used to access members or invoke methods on an object that may be null. If the object is null, the expression returns null instead of throwing a null reference exception.
โณ๏ธChecking for null is probably what you do quite often, for example, to prevent a null reference exception when invoking properties. Using if-statements for numerous null checking makes code cumbersome and lengthy.
โณ๏ธThe null conditional operator allows checking one or more expressions for null in a call chain, which is called null propagation. Such a notation can be written in a single line whereas a number of if-else statements typically occupy many lines.
๐กIn the comments I attached an example in JavaScript: Replace if statement with Optional chaining.
โณ๏ธ Can you make the example cleaner ? Do you have any other suggestions?
Thank you for reading ๐
  โณ๏ธThe null conditional operator, also known as the null propagation operator or the safe navigation operator, is a feature introduced in C# 6.0 that allows you to write cleaner and more concise code when dealing with potentially null reference types.
โณ๏ธThe null conditional operator is represented by a question mark followed by a period (?.) and is used to access members or invoke methods on an object that may be null. If the object is null, the expression returns null instead of throwing a null reference exception.
โณ๏ธChecking for null is probably what you do quite often, for example, to prevent a null reference exception when invoking properties. Using if-statements for numerous null checking makes code cumbersome and lengthy.
โณ๏ธThe null conditional operator allows checking one or more expressions for null in a call chain, which is called null propagation. Such a notation can be written in a single line whereas a number of if-else statements typically occupy many lines.
๐กIn the comments I attached an example in JavaScript: Replace if statement with Optional chaining.
โณ๏ธ Can you make the example cleaner ? Do you have any other suggestions?
Thank you for reading ๐
โ๏ธ Avoid else after return
โณ๏ธ This principle is a guideline in clean code development that suggests avoiding the use of an else statement immediately after a return statement in a function or method.
โณ๏ธ When a return statement is encountered in a function, it immediately exits the function and returns control to the calling code. Any code following the return statement within the same block will not be executed. In many cases, including an else statement after a return is redundant and can be safely removed.
โณ๏ธ Following the "Avoid else after return" principle helps in writing cleaner, more maintainable code by simplifying control flow and improving code readability.
โณ๏ธ In the attached image, an example of how to apply this principle.
โ Bad: Violates the "Avoid else after return" principle.
โ๏ธ Good: Refactoring the code, the else clause have been eliminated.
๐ก Short: The conditional operator (? :) is used to directly return either "Pass" or "Fail" based on the condition. This eliminates the need for an if-else statement.
  โณ๏ธ This principle is a guideline in clean code development that suggests avoiding the use of an else statement immediately after a return statement in a function or method.
โณ๏ธ When a return statement is encountered in a function, it immediately exits the function and returns control to the calling code. Any code following the return statement within the same block will not be executed. In many cases, including an else statement after a return is redundant and can be safely removed.
โณ๏ธ Following the "Avoid else after return" principle helps in writing cleaner, more maintainable code by simplifying control flow and improving code readability.
โณ๏ธ In the attached image, an example of how to apply this principle.
โ Bad: Violates the "Avoid else after return" principle.
โ๏ธ Good: Refactoring the code, the else clause have been eliminated.
๐ก Short: The conditional operator (? :) is used to directly return either "Pass" or "Fail" based on the condition. This eliminates the need for an if-else statement.
โ๏ธ Function names should say what they do
Function names should be clear and descriptive, providing a clear indication of what the function does. This makes it easier for other developers to understand the purpose of the function without having to read through the implementation details.
This is important because function names serve as a form of documentation and make it easier for other developers to understand the purpose and behavior of the code.
Following this principle helps make your code more readable, understandable, and maintainable.
Thank you for reading ๐
  Function names should be clear and descriptive, providing a clear indication of what the function does. This makes it easier for other developers to understand the purpose of the function without having to read through the implementation details.
This is important because function names serve as a form of documentation and make it easier for other developers to understand the purpose and behavior of the code.
Following this principle helps make your code more readable, understandable, and maintainable.
Thank you for reading ๐
โ๏ธ Use searchable names
We will read more code than we will ever write. It's important that the code we do write must be readable and searchable. By not naming variables that end up being meaningful for understanding our program, we hurt our readers. Make your names searchable.
Using searchable names means that variable, function, and class names should be clear and unambiguous so that other developers can easily understand what they do.
Thank you for reading ๐
  We will read more code than we will ever write. It's important that the code we do write must be readable and searchable. By not naming variables that end up being meaningful for understanding our program, we hurt our readers. Make your names searchable.
Using searchable names means that variable, function, and class names should be clear and unambiguous so that other developers can easily understand what they do.
Thank you for reading ๐
