1. Guard Clause
The ward statement is used to deal with special situations in advance, avoid deep nested conditional judgments, and make the code logic clearer.
Traditional nesting writing
public string ProcessOrder(int quantity, double price, double discount) { if (quantity > 0) { if (price > 0) { if (discount >= 0) { double total = quantity * price * (1 - discount); return $"Total cost: {total}"; } else { return "Discount must be non-negative"; } } else { return "Price must be positive"; } } else { return "Quantity must be positive"; } }
Improved using harbor statement
public string ProcessOrder(int quantity, double price, double discount) { // Wei sentence: Check for special circumstances in advance if (quantity <= 0) return "Quantity must be positive"; if (price <= 0) return "Price must be positive"; if (discount < 0) return "Discount must be non-negative"; // Main logic: No nesting required double total = quantity * price * (1 - discount); return $"Total cost: {total}"; }
advantage:
- Reduce nesting levels and make the code easier to read.
- Handle exceptions in advance, and the logic is clearer.
2. Replace nested conditions with enumeration
Enumerations can be used to replace nested conditional judgments in certain scenarios, especially when there are multiple fixed states or types in the code.
Traditional nesting writing
public string GetPermissionLevel(string role) { if (role == "admin") { return "Full access"; } else if (role == "editor") { return "Edit access"; } else if (role == "viewer") { return "View access"; } else { return "No access"; } }
Improvements to use enumeration
public enum Role { Admin, Editor, Viewer } public string GetPermissionLevel(Role role) { switch (role) { case : return "Full access"; case : return "Edit access"; case : return "View access"; default: return "No access"; } }
advantage:
- Enumeration values have clear semantics, avoiding hard-coded strings.
- Reduce nested condition judgments and make the code more concise.
3. Use dictionary mapping to further optimize
If the behavior corresponding to each enum value is fixed, a dictionary can be used to further simplify the logic.
Improved using dictionary mapping
public enum Role { Admin, Editor, Viewer } public class PermissionManager { private static readonly Dictionary<Role, string> PermissionLevels = new Dictionary<Role, string> { { , "Full access" }, { , "Edit access" }, { , "View access" } }; public string GetPermissionLevel(Role role) { if ((role, out var permissionLevel)) { return permissionLevel; } return "No access"; } }
advantage:
- Completely eliminate nested condition judgment.
- When adding a new role, you only need to update the dictionary without modifying the function logic.
4. The Single Responsibility Principle (SRP)
Each function or class should be responsible for only one task, which can improve the readability, maintainability and testability of the code.
Before improvement
public string ProcessOrder(int quantity, double price, double discount) { if (quantity <= 0) return "Quantity must be positive"; if (price <= 0) return "Price must be positive"; if (discount < 0) return "Discount must be non-negative"; double total = quantity * price * (1 - discount); return $"Total cost: {total}"; }
After improvement
public class OrderProcessor { public void ValidateInput(int quantity, double price, double discount) { if (quantity <= 0) throw new ArgumentException("Quantity must be positive"); if (price <= 0) throw new ArgumentException("Price must be positive"); if (discount < 0) throw new ArgumentException("Discount must be non-negative"); } public double CalculateTotal(int quantity, double price, double discount) { return quantity * price * (1 - discount); } public string ProcessOrder(int quantity, double price, double discount) { ValidateInput(quantity, price, discount); double total = CalculateTotal(quantity, price, discount); return $"Total cost: {total}"; } }
advantage:
- Each function does only one thing and has clear responsibilities.
- Easier to test and reuse.
5. Avoid duplicate code (DRY - Don’t Repeat Yourself)
Repeating code will increase maintenance costs and easily introduce errors. Repetition can be avoided by extracting public logic into functions or tool classes.
Before improvement
public double CalculateAreaOfSquare(double side) { return side * side; } public double CalculateAreaOfRectangle(double length, double width) { return length * width; }
After improvement
public double CalculateArea(string shape, params double[] dimensions) { switch (shape) { case "square": return dimensions[0] * dimensions[0]; case "rectangle": return dimensions[0] * dimensions[1]; default: throw new ArgumentException("Unsupported shape"); } }
advantage:
- Reduce duplicate code and make the logic more concentrated.
- It's easier to expand new features.
6. Use meaningful naming
The naming of variables, functions and classes should clearly express their purpose, avoiding the use of ambiguity or abbreviation.
Before improvement
public double Calc(double a, double b) { return a * b; }
After improvement
public double CalculateArea(double length, double width) { return length * width; }
advantage:
- The code is easier to read and reduces the cost of understanding.
- Reduce the necessity of comments.
7. Use exception handling
Rationally using exception handling can improve the robustness of the code and avoid program crashes.
Before improvement
public double Divide(double a, double b) { return a / b; // If b is 0, an exception will be thrown}
After improvement
public double Divide(double a, double b) { if (b == 0) throw new DivideByZeroException("Division by zero is not allowed"); return a / b; }
advantage:
- Clearly handle exceptions to avoid unexpected errors.
- Improve code reliability.
8. Write unit tests
Unit testing ensures the correctness of the code and provides security when modifying the code.
Example
using ; [TestClass] public class MathOperationsTests { [TestMethod] public void TestAdd() { (5, Add(2, 3)); (0, Add(-1, 1)); } public int Add(int a, int b) { return a + b; } }
advantage:
- Make sure the code is correct.
- Supports refactoring and continuous integration.
9. Use design mode
Design patterns are a classic solution to common problems that can improve the scalability and maintainability of your code.
Example: Factory Mode
public interface IAnimal { string Speak(); } public class Dog : IAnimal { public string Speak() { return "Woof!"; } } public class Cat : IAnimal { public string Speak() { return "Meow!"; } } public class AnimalFactory { public static IAnimal CreateAnimal(string type) { switch (type) { case "dog": return new Dog(); case "cat": return new Cat(); default: throw new ArgumentException("Unknown animal type"); } } } // usevar dog = ("dog"); (()); // Output: Woof!
advantage:
- Creation and use of decoupled objects.
- Improve code flexibility.
10. Code comments and documentation
Good comments and documentation can help others understand the intent and implementation details of the code.
Example
/// <summary> /// Calculate the rectangle area./// </summary> /// <param name="length">Length of rectangle</param>/// <param name="width">Width of rectangle</param>/// <returns> Area of the rectangle</returns>public double CalculateArea(double length, double width) { return length * width; }
advantage:
- Improve the readability of the code.
- Convenient team collaboration and maintenance.
11. Use version control tools
Use version control tools such as Git to track code changes for easy collaboration and rollback.
Example
git init git add . git commit -m "Initial commit"
advantage:
- Record code history for easy backtracking.
- Support team collaborative development.
12. Code Refactoring
Regularly refactor the code, optimize structure and performance, and maintain the healthy state of the code.
Before improvement
public List<int> ProcessData(List<int> data) { List<int> result = new List<int>(); foreach (var item in data) { if (item % 2 == 0) { (item * 2); } } return result; }
After improvement
public List<int> ProcessData(List<int> data) { return (item => item % 2 == 0).Select(item => item * 2).ToList(); }
advantage:
- The code is more concise and the performance is better.
- Reduce potential errors.
Summarize
The following tips can significantly improve code quality:
- Wei's sentence
- Replace nested conditions with enumeration
- Using dictionary mapping
- Single responsibility principle
- Avoid duplicate code
- Use meaningful naming
- Use exception handling
- Writing unit tests
- Use design mode
- Code comments and documentation
- Use version control tools
- Code Refactoring
Combining these techniques, you can write high-quality, easy-to-maintain code.
This is the end of this article about the skills and practices of using C# to improve code quality. For more related content on improving code quality in C#, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!