โ๏ธ ๐ก๐๐น๐น ๐ฐ๐ต๐ฒ๐ฐ๐ธ๐ ๐๐ต๐ผ๐๐น๐ฑ ๐ป๐ผ๐ ๐ฏ๐ฒ ๐๐๐ฒ๐ฑ ๐๐ถ๐๐ต ๐ถ๐
โ In C#, the ๐ถ๐ ๐ผ๐ฝ๐ฒ๐ฟ๐ฎ๐๐ผ๐ฟ is used to determine whether an object is compatible with a specific type. It evaluates to true if the object can be cast to the specified type without causing an exception, and false otherwise. It also returns false for null objects.
โ The ๐ถ๐ ๐ผ๐ฝ๐ฒ๐ฟ๐ฎ๐๐ผ๐ฟ can be useful in the following scenarios:
โพ๏ธ To check the run-time type of an expression.
โพ๏ธ To check for null.
โพ๏ธ To check for non-null using a negation pattern.
โพ๏ธ Match elements of a list or array using list patterns.
๐ก ๐ก๐๐น๐น ๐ฐ๐ต๐ฒ๐ฐ๐ธ๐ ๐๐ต๐ผ๐๐น๐ฑ ๐ป๐ผ๐ ๐ฏ๐ฒ ๐๐๐ฒ๐ฑ ๐๐ถ๐๐ต ๐ถ๐
Thereโs no need to null test in conjunction with an is test. null is not an instance of anything, so a null check is redundant.
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐
โ In C#, the ๐ถ๐ ๐ผ๐ฝ๐ฒ๐ฟ๐ฎ๐๐ผ๐ฟ is used to determine whether an object is compatible with a specific type. It evaluates to true if the object can be cast to the specified type without causing an exception, and false otherwise. It also returns false for null objects.
โ The ๐ถ๐ ๐ผ๐ฝ๐ฒ๐ฟ๐ฎ๐๐ผ๐ฟ can be useful in the following scenarios:
โพ๏ธ To check the run-time type of an expression.
โพ๏ธ To check for null.
โพ๏ธ To check for non-null using a negation pattern.
โพ๏ธ Match elements of a list or array using list patterns.
๐ก ๐ก๐๐น๐น ๐ฐ๐ต๐ฒ๐ฐ๐ธ๐ ๐๐ต๐ผ๐๐น๐ฑ ๐ป๐ผ๐ ๐ฏ๐ฒ ๐๐๐ฒ๐ฑ ๐๐ถ๐๐ต ๐ถ๐
Thereโs no need to null test in conjunction with an is test. null is not an instance of anything, so a null check is redundant.
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐
โ๏ธ ๐ฃ๐ฟ๐ฒ๐ณ๐ฒ๐ฟ ๐๐ต๐ฒ ๐ถ๐ ๐๐ฒ๐๐๐ผ๐ฟ๐ฑ ๐ข๐๐ฒ๐ฟ ๐๐ต๐ฒ == ๐ข๐ฝ๐ฒ๐ฟ๐ฎ๐๐ผ๐ฟ ๐๐ผ ๐ฐ๐ต๐ฒ๐ฐ๐ธ ๐ณ๐ผ๐ฟ ๐ป๐๐น๐น
โ The primary reason to prefer ๐ถ๐ for null checks is its avoidance of potential operator overloading issues. Operator overloading allows programmers to define custom behavior for operators like == for their classes. While useful, this feature can introduce unexpected behavior when checking for null.
๐ก Consider a scenario where a class Student overloads the == operator to compare the values of its properties rather than object references. If you use == to check for null, you might not get the expected result, as the overloaded == would compare property values instead of checking for null.
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐
โ The primary reason to prefer ๐ถ๐ for null checks is its avoidance of potential operator overloading issues. Operator overloading allows programmers to define custom behavior for operators like == for their classes. While useful, this feature can introduce unexpected behavior when checking for null.
๐ก Consider a scenario where a class Student overloads the == operator to compare the values of its properties rather than object references. If you use == to check for null, you might not get the expected result, as the overloaded == would compare property values instead of checking for null.
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐
โ๏ธ ๐๐๐ป๐ฐ๐๐ถ๐ผ๐ป๐ ๐๐ต๐ผ๐๐น๐ฑ ๐ฑ๐ผ ๐ผ๐ป๐ฒ ๐๐ต๐ถ๐ป๐ด
โ This principle suggests that a function should have only one reason to change, meaning that it should perform a single, well-defined task and not multiple unrelated tasks. This approach increases readability, maintainability, and testability of your code.
โ A function that does too many things or has too many responsibilities can become difficult to understand, test, and maintain.
๐๐บ๐ฝ๐น๐ฒ๐บ๐ฒ๐ป๐๐ฎ๐๐ถ๐ผ๐ป:
โพ๏ธ Identify the single responsibility of the function. What is the one thing that the function should do?
โพ๏ธ Extract all unrelated code from the function. This code can be moved to other functions or classes.
โพ๏ธ Give the function a descriptive name that reflects its single responsibility.
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐
โ This principle suggests that a function should have only one reason to change, meaning that it should perform a single, well-defined task and not multiple unrelated tasks. This approach increases readability, maintainability, and testability of your code.
โ A function that does too many things or has too many responsibilities can become difficult to understand, test, and maintain.
๐๐บ๐ฝ๐น๐ฒ๐บ๐ฒ๐ป๐๐ฎ๐๐ถ๐ผ๐ป:
โพ๏ธ Identify the single responsibility of the function. What is the one thing that the function should do?
โพ๏ธ Extract all unrelated code from the function. This code can be moved to other functions or classes.
โพ๏ธ Give the function a descriptive name that reflects its single responsibility.
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐
โ๏ธ ๐จ๐๐ฒ ๐๐๐ฟ๐ถ๐ป๐ด.๐๐พ๐๐ฎ๐น๐ ๐ถ๐ป๐๐๐ฒ๐ฎ๐ฑ ๐ผ๐ณ ๐ง๐ผ๐จ๐ฝ๐ฝ๐ฒ๐ฟ()/๐ง๐ผ๐๐ผ๐๐ฒ๐ฟ() ๐๐ต๐ฒ๐ป ๐ฐ๐ผ๐บ๐ฝ๐ฎ๐ฟ๐ถ๐ป๐ด ๐๐๐ฟ๐ถ๐ป๐ด๐
๐ Using ๐ง๐ผ๐จ๐ฝ๐ฝ๐ฒ๐ฟ() and ๐ง๐ผ๐๐ผ๐๐ฒ๐ฟ() for case conversion in C# can impact performance due to memory allocation, string copying, and potential garbage collection, especially in situations involving large strings or frequent conversions.
๐ ๐ฆ๐๐ฟ๐ถ๐ป๐ด.๐๐พ๐๐ฎ๐น๐ is faster than ToUpper() or ToLower() due to direct character comparison, avoiding memory allocation, and reducing overhead for case-insensitive string comparison.
๐ฅ To perform string comparison , it's better to use the built-in comparison methods like ๐ฆ๐๐ฟ๐ถ๐ป๐ด.๐๐พ๐๐ฎ๐น๐ with appropriate StringComparison options, which handle case-insensitivity and cultural considerations correctly while maintaining better performance and accuracy.
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐
#csharp #dotnet #programming #cleancode
๐ Using ๐ง๐ผ๐จ๐ฝ๐ฝ๐ฒ๐ฟ() and ๐ง๐ผ๐๐ผ๐๐ฒ๐ฟ() for case conversion in C# can impact performance due to memory allocation, string copying, and potential garbage collection, especially in situations involving large strings or frequent conversions.
๐ ๐ฆ๐๐ฟ๐ถ๐ป๐ด.๐๐พ๐๐ฎ๐น๐ is faster than ToUpper() or ToLower() due to direct character comparison, avoiding memory allocation, and reducing overhead for case-insensitive string comparison.
๐ฅ To perform string comparison , it's better to use the built-in comparison methods like ๐ฆ๐๐ฟ๐ถ๐ป๐ด.๐๐พ๐๐ฎ๐น๐ with appropriate StringComparison options, which handle case-insensitivity and cultural considerations correctly while maintaining better performance and accuracy.
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐
#csharp #dotnet #programming #cleancode
๐1
โ๏ธ ๐๐๐ผ๐ถ๐ฑ ๐ฒ๐น๐๐ฒ ๐ฎ๐ณ๐๐ฒ๐ฟ ๐ฟ๐ฒ๐๐๐ฟ๐ป
โ 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 ๐ฒ๐น๐๐ฒ ๐๐๐ฎ๐๐ฒ๐บ๐ฒ๐ป๐ after a return is redundant and can be safely removed.
โ To implement this principle, simply ๐ฟ๐ฒ๐บ๐ผ๐๐ฒ ๐๐ต๐ฒ ๐ฒ๐น๐๐ฒ ๐๐๐ฎ๐๐ฒ๐บ๐ฒ๐ป๐ after any return statement. If you need to execute code if the if condition is not met, you can move that code to the end of the function, outside of the if statement.
๐ก ๐ง๐ต๐ฒ ๐ฐ๐ผ๐ป๐ฑ๐ถ๐๐ถ๐ผ๐ป๐ฎ๐น ๐ผ๐ฝ๐ฒ๐ฟ๐ฎ๐๐ผ๐ฟ is a good choice when you have a simple conditional logic. While it can be used to simplify code in some cases, it should be used judiciously to maintain code readability.
๐ฅ Following the "๐๐๐ผ๐ถ๐ฑ ๐ฒ๐น๐๐ฒ ๐ฎ๐ณ๐๐ฒ๐ฟ ๐ฟ๐ฒ๐๐๐ฟ๐ป" principle helps in writing cleaner, more maintainable code by simplifying control flow and improving code readability.
โ ๐ช๐ต๐ถ๐ฐ๐ต ๐ผ๐ป๐ฒ ๐ฑ๐ผ ๐๐ผ๐ ๐ฝ๐ฟ๐ฒ๐ณ๐ฒ๐ฟ?
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐
โ 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 ๐ฒ๐น๐๐ฒ ๐๐๐ฎ๐๐ฒ๐บ๐ฒ๐ป๐ after a return is redundant and can be safely removed.
โ To implement this principle, simply ๐ฟ๐ฒ๐บ๐ผ๐๐ฒ ๐๐ต๐ฒ ๐ฒ๐น๐๐ฒ ๐๐๐ฎ๐๐ฒ๐บ๐ฒ๐ป๐ after any return statement. If you need to execute code if the if condition is not met, you can move that code to the end of the function, outside of the if statement.
๐ก ๐ง๐ต๐ฒ ๐ฐ๐ผ๐ป๐ฑ๐ถ๐๐ถ๐ผ๐ป๐ฎ๐น ๐ผ๐ฝ๐ฒ๐ฟ๐ฎ๐๐ผ๐ฟ is a good choice when you have a simple conditional logic. While it can be used to simplify code in some cases, it should be used judiciously to maintain code readability.
๐ฅ Following the "๐๐๐ผ๐ถ๐ฑ ๐ฒ๐น๐๐ฒ ๐ฎ๐ณ๐๐ฒ๐ฟ ๐ฟ๐ฒ๐๐๐ฟ๐ป" principle helps in writing cleaner, more maintainable code by simplifying control flow and improving code readability.
โ ๐ช๐ต๐ถ๐ฐ๐ต ๐ผ๐ป๐ฒ ๐ฑ๐ผ ๐๐ผ๐ ๐ฝ๐ฟ๐ฒ๐ณ๐ฒ๐ฟ?
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐
โ๏ธ ๐๐ป๐ฐ๐ฎ๐ฝ๐๐๐น๐ฎ๐๐ฒ ๐ฐ๐ผ๐ป๐ฑ๐ถ๐๐ถ๐ผ๐ป๐ฎ๐น๐
โ ๐๐ป๐ฐ๐ฎ๐ฝ๐๐๐น๐ฎ๐๐ฒ ๐ฐ๐ผ๐ป๐ฑ๐ถ๐๐ถ๐ผ๐ป๐ฎ๐น๐ is a practice of clean coding where you replace complex conditional logic with well-named methods to make your code more readable and maintainable.
๐ฅ ๐ง๐ต๐ฒ ๐ฎ๐ฑ๐๐ฎ๐ป๐๐ฎ๐ด๐ฒ๐ ๐ผ๐ณ ๐ฒ๐ป๐ฐ๐ฎ๐ฝ๐๐๐น๐ฎ๐๐ถ๐ป๐ด ๐ฐ๐ผ๐ป๐ฑ๐ถ๐๐ถ๐ผ๐ป๐ฎ๐น๐:
โพ๏ธ ๐๐บ๐ฝ๐ฟ๐ผ๐๐ฒ๐ ๐ฟ๐ฒ๐ฎ๐ฑ๐ฎ๐ฏ๐ถ๐น๐ถ๐๐: Code reads more like a high-level language, which improves understanding.
โพ๏ธ ๐ฅ๐ฒ๐ฑ๐๐ฐ๐ฒ๐ ๐ฑ๐๐ฝ๐น๐ถ๐ฐ๐ฎ๐๐ถ๐ผ๐ป: If a complex condition is used in more than one place, it's better to keep the logic in one place.
โพ๏ธ ๐ฆ๐ถ๐บ๐ฝ๐น๐ถ๐ณ๐ถ๐ฒ๐ ๐ฐ๐ผ๐ฑ๐ฒ: It's easier to understand a method call with a well-named method than to understand a complex conditional.
โพ๏ธ ๐๐ฎ๐๐ถ๐ฒ๐ฟ ๐๐ผ ๐๐ฒ๐๐: Encapsulated conditionals can be separately tested, ensuring that all edge-cases are covered.
๐ป ๐๐ผ๐ ๐๐ผ ๐ถ๐บ๐ฝ๐น๐ฒ๐บ๐ฒ๐ป๐ ๐ฒ๐ป๐ฐ๐ฎ๐ฝ๐๐๐น๐ฎ๐๐ฒ ๐ฐ๐ผ๐ป๐ฑ๐ถ๐๐ถ๐ผ๐ป๐ฎ๐น๐:
To implement encapsulate conditionals, simply extract the conditional logic into a private method. The method should have a clear and concise name that describes what it does.
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐
โ ๐๐ป๐ฐ๐ฎ๐ฝ๐๐๐น๐ฎ๐๐ฒ ๐ฐ๐ผ๐ป๐ฑ๐ถ๐๐ถ๐ผ๐ป๐ฎ๐น๐ is a practice of clean coding where you replace complex conditional logic with well-named methods to make your code more readable and maintainable.
๐ฅ ๐ง๐ต๐ฒ ๐ฎ๐ฑ๐๐ฎ๐ป๐๐ฎ๐ด๐ฒ๐ ๐ผ๐ณ ๐ฒ๐ป๐ฐ๐ฎ๐ฝ๐๐๐น๐ฎ๐๐ถ๐ป๐ด ๐ฐ๐ผ๐ป๐ฑ๐ถ๐๐ถ๐ผ๐ป๐ฎ๐น๐:
โพ๏ธ ๐๐บ๐ฝ๐ฟ๐ผ๐๐ฒ๐ ๐ฟ๐ฒ๐ฎ๐ฑ๐ฎ๐ฏ๐ถ๐น๐ถ๐๐: Code reads more like a high-level language, which improves understanding.
โพ๏ธ ๐ฅ๐ฒ๐ฑ๐๐ฐ๐ฒ๐ ๐ฑ๐๐ฝ๐น๐ถ๐ฐ๐ฎ๐๐ถ๐ผ๐ป: If a complex condition is used in more than one place, it's better to keep the logic in one place.
โพ๏ธ ๐ฆ๐ถ๐บ๐ฝ๐น๐ถ๐ณ๐ถ๐ฒ๐ ๐ฐ๐ผ๐ฑ๐ฒ: It's easier to understand a method call with a well-named method than to understand a complex conditional.
โพ๏ธ ๐๐ฎ๐๐ถ๐ฒ๐ฟ ๐๐ผ ๐๐ฒ๐๐: Encapsulated conditionals can be separately tested, ensuring that all edge-cases are covered.
๐ป ๐๐ผ๐ ๐๐ผ ๐ถ๐บ๐ฝ๐น๐ฒ๐บ๐ฒ๐ป๐ ๐ฒ๐ป๐ฐ๐ฎ๐ฝ๐๐๐น๐ฎ๐๐ฒ ๐ฐ๐ผ๐ป๐ฑ๐ถ๐๐ถ๐ผ๐ป๐ฎ๐น๐:
To implement encapsulate conditionals, simply extract the conditional logic into a private method. The method should have a clear and concise name that describes what it does.
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐
โ๏ธ ๐ฅ๐ฒ๐ฝ๐น๐ฎ๐ฐ๐ฒ ๐ถ๐ณ ๐๐๐ฎ๐๐ฒ๐บ๐ฒ๐ป๐ ๐๐ถ๐๐ต ๐ก๐๐น๐น ๐๐ผ๐ป๐ฑ๐ถ๐๐ถ๐ผ๐ป๐ฎ๐น ๐ข๐ฝ๐ฒ๐ฟ๐ฎ๐๐ผ๐ฟ
โ The ๐ป๐๐น๐น ๐ฐ๐ผ๐ป๐ฑ๐ถ๐๐ถ๐ผ๐ป๐ฎ๐น ๐ผ๐ฝ๐ฒ๐ฟ๐ฎ๐๐ผ๐ฟ, 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 ๐ป๐๐น๐น ๐ฐ๐ผ๐ป๐ฑ๐ถ๐๐ถ๐ผ๐ป๐ฎ๐น ๐ผ๐ฝ๐ฒ๐ฟ๐ฎ๐๐ผ๐ฟ 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.
๐ฅ ๐๐ฑ๐๐ฎ๐ป๐๐ฎ๐ด๐ฒ๐ ๐ผ๐ณ ๐๐๐ถ๐ป๐ด ๐๐ต๐ฒ ๐ป๐๐น๐น ๐ฐ๐ผ๐ป๐ฑ๐ถ๐๐ถ๐ผ๐ป๐ฎ๐น ๐ผ๐ฝ๐ฒ๐ฟ๐ฎ๐๐ผ๐ฟ:
โพ๏ธThe null conditional operator can make your code more concise and readable.
โพ๏ธThe null conditional operator can help to avoid null-reference exceptions.
โพ๏ธThe null conditional operator can be used to chain together multiple member or element accesses, even if some of the members or elements may be null.
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐
โ The ๐ป๐๐น๐น ๐ฐ๐ผ๐ป๐ฑ๐ถ๐๐ถ๐ผ๐ป๐ฎ๐น ๐ผ๐ฝ๐ฒ๐ฟ๐ฎ๐๐ผ๐ฟ, 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 ๐ป๐๐น๐น ๐ฐ๐ผ๐ป๐ฑ๐ถ๐๐ถ๐ผ๐ป๐ฎ๐น ๐ผ๐ฝ๐ฒ๐ฟ๐ฎ๐๐ผ๐ฟ 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.
๐ฅ ๐๐ฑ๐๐ฎ๐ป๐๐ฎ๐ด๐ฒ๐ ๐ผ๐ณ ๐๐๐ถ๐ป๐ด ๐๐ต๐ฒ ๐ป๐๐น๐น ๐ฐ๐ผ๐ป๐ฑ๐ถ๐๐ถ๐ผ๐ป๐ฎ๐น ๐ผ๐ฝ๐ฒ๐ฟ๐ฎ๐๐ผ๐ฟ:
โพ๏ธThe null conditional operator can make your code more concise and readable.
โพ๏ธThe null conditional operator can help to avoid null-reference exceptions.
โพ๏ธThe null conditional operator can be used to chain together multiple member or element accesses, even if some of the members or elements may be null.
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐
๐ก๐ ๐ผ๐ฑ๐ถ๐ณ๐๐ถ๐ป๐ด ๐ฃ๐ฎ๐๐๐ฒ๐ฑ ๐ข๐ฏ๐ท๐ฒ๐ฐ๐๐ ๐ถ๐ป ๐#
โ ๐ ๐ผ๐ฑ๐ถ๐ณ๐ ๐๐ต๐ฒ ๐ผ๐ฏ๐ท๐ฒ๐ฐ๐ ๐๐ต๐ฒ๐ฟ๐ฒ ๐บ๐ฒ๐๐ต๐ผ๐ฑโ๐ ๐ฟ๐ฒ๐๐๐ฟ๐ป ๐๐๐ฝ๐ฒ ๐ถ๐ ๐๐ผ๐ถ๐ฑ:
Modify objects in-place (return type ๐๐ผ๐ถ๐ฑ) for simple state changes.
โ ๐๐ฟ๐ฒ๐ฎ๐๐ฒ ๐ฎ ๐ก๐ฒ๐ ๐๐ป๐๐๐ฎ๐ป๐ฐ๐ฒ ๐ฎ๐ป๐ฑ ๐ฅ๐ฒ๐๐๐ฟ๐ป ๐๐:
Create and ๐ฟ๐ฒ๐๐๐ฟ๐ป a new instance for immutability or history tracking.
โ ๐จ๐๐ฒ ๐ฟ๐ฒ๐ณ ๐ธ๐ฒ๐๐๐ผ๐ฟ๐ฑ:
Use ๐ฟ๐ฒ๐ณ to modify the original object, being cautious about side effects.
โ ๐จ๐๐ฒ ๐ถ๐ป ๐ธ๐ฒ๐๐๐ผ๐ฟ๐ฑ:
Use ๐ถ๐ป to pass objects as read-only references.
โ ๐จ๐๐ฒ ๐ผ๐๐ ๐ธ๐ฒ๐๐๐ผ๐ฟ๐ฑ:
Use ๐ผ๐๐ to return and initialize objects without prior initialization.
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐
โ ๐ ๐ผ๐ฑ๐ถ๐ณ๐ ๐๐ต๐ฒ ๐ผ๐ฏ๐ท๐ฒ๐ฐ๐ ๐๐ต๐ฒ๐ฟ๐ฒ ๐บ๐ฒ๐๐ต๐ผ๐ฑโ๐ ๐ฟ๐ฒ๐๐๐ฟ๐ป ๐๐๐ฝ๐ฒ ๐ถ๐ ๐๐ผ๐ถ๐ฑ:
Modify objects in-place (return type ๐๐ผ๐ถ๐ฑ) for simple state changes.
โ ๐๐ฟ๐ฒ๐ฎ๐๐ฒ ๐ฎ ๐ก๐ฒ๐ ๐๐ป๐๐๐ฎ๐ป๐ฐ๐ฒ ๐ฎ๐ป๐ฑ ๐ฅ๐ฒ๐๐๐ฟ๐ป ๐๐:
Create and ๐ฟ๐ฒ๐๐๐ฟ๐ป a new instance for immutability or history tracking.
โ ๐จ๐๐ฒ ๐ฟ๐ฒ๐ณ ๐ธ๐ฒ๐๐๐ผ๐ฟ๐ฑ:
Use ๐ฟ๐ฒ๐ณ to modify the original object, being cautious about side effects.
โ ๐จ๐๐ฒ ๐ถ๐ป ๐ธ๐ฒ๐๐๐ผ๐ฟ๐ฑ:
Use ๐ถ๐ป to pass objects as read-only references.
โ ๐จ๐๐ฒ ๐ผ๐๐ ๐ธ๐ฒ๐๐๐ผ๐ฟ๐ฑ:
Use ๐ผ๐๐ to return and initialize objects without prior initialization.
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐
โ๏ธ๐ฅ๐ฒ๐น๐ฎ๐๐ถ๐ผ๐ป๐ฎ๐น ๐ฃ๐ฎ๐๐๐ฒ๐ฟ๐ป๐ ๐ ๐ฎ๐๐ฐ๐ต๐ถ๐ป๐ด
โ ๐ฅ๐ฒ๐น๐ฎ๐๐ถ๐ผ๐ป๐ฎ๐น ๐ฃ๐ฎ๐๐๐ฒ๐ฟ๐ป๐ ๐ ๐ฎ๐๐ฐ๐ต๐ถ๐ป๐ด is a feature introduced in ๐# ๐ต that enhances the pattern matching capabilities of the language. Pattern matching is a way to compare values against patterns.
โ ๐ฅ๐ฒ๐น๐ฎ๐๐ถ๐ผ๐ป๐ฎ๐น ๐ฃ๐ฎ๐๐๐ฒ๐ฟ๐ป๐ ๐ ๐ฎ๐๐ฐ๐ต๐ถ๐ป๐ด specifically allows you to perform pattern matching based on relational comparisons, such as greater than, less than, greater than or equal to, and less than or equal to comparisons.
โ It is a ๐ณ๐๐ป๐ฐ๐๐ถ๐ผ๐ป๐ฎ๐น programming technique, which means that it focuses on the evaluation of expressions rather than the control flow of your code.
โ ๐ฅ๐ฒ๐น๐ฎ๐๐ถ๐ผ๐ป๐ฎ๐น ๐ฃ๐ฎ๐๐๐ฒ๐ฟ๐ป๐ ๐ ๐ฎ๐๐ฐ๐ต๐ถ๐ป๐ด is a feature introduced in ๐# ๐ต that enhances the pattern matching capabilities of the language. Pattern matching is a way to compare values against patterns.
โ ๐ฅ๐ฒ๐น๐ฎ๐๐ถ๐ผ๐ป๐ฎ๐น ๐ฃ๐ฎ๐๐๐ฒ๐ฟ๐ป๐ ๐ ๐ฎ๐๐ฐ๐ต๐ถ๐ป๐ด specifically allows you to perform pattern matching based on relational comparisons, such as greater than, less than, greater than or equal to, and less than or equal to comparisons.
โ It is a ๐ณ๐๐ป๐ฐ๐๐ถ๐ผ๐ป๐ฎ๐น programming technique, which means that it focuses on the evaluation of expressions rather than the control flow of your code.
โ๏ธ๐ฅ๐ฒ๐น๐ฎ๐๐ถ๐ผ๐ป๐ฎ๐น ๐ฃ๐ฎ๐๐๐ฒ๐ฟ๐ป๐ ๐ ๐ฎ๐๐ฐ๐ต๐ถ๐ป๐ด
โ ๐ฅ๐ฒ๐น๐ฎ๐๐ถ๐ผ๐ป๐ฎ๐น ๐ฃ๐ฎ๐๐๐ฒ๐ฟ๐ป๐ ๐ ๐ฎ๐๐ฐ๐ต๐ถ๐ป๐ด is a feature introduced in ๐# ๐ต that enhances the pattern matching capabilities of the language. Pattern matching is a way to compare values against patterns.
โ ๐ฅ๐ฒ๐น๐ฎ๐๐ถ๐ผ๐ป๐ฎ๐น ๐ฃ๐ฎ๐๐๐ฒ๐ฟ๐ป๐ ๐ ๐ฎ๐๐ฐ๐ต๐ถ๐ป๐ด specifically allows you to perform pattern matching based on relational comparisons, such as greater than, less than, greater than or equal to, and less than or equal to comparisons.
โ It is a ๐ณ๐๐ป๐ฐ๐๐ถ๐ผ๐ป๐ฎ๐น programming technique, which means that it focuses on the evaluation of expressions rather than the control flow of your code.
๐ฅ ๐๐ฑ๐๐ฎ๐ป๐๐ฎ๐ด๐ฒ๐ ๐ผ๐ณ ๐ฟ๐ฒ๐น๐ฎ๐๐ถ๐ผ๐ป๐ฎ๐น ๐ฝ๐ฎ๐๐๐ฒ๐ฟ๐ป๐ ๐บ๐ฎ๐๐ฐ๐ต๐ถ๐ป๐ด:
โพ๏ธ ๐๐ผ๐ป๐ฐ๐ถ๐๐ฒ๐ป๐ฒ๐๐: Relational patterns matching can be used to create more concise and readable code.
โพ๏ธ ๐๐ ๐ฝ๐ฟ๐ฒ๐๐๐ถ๐๐ฒ๐ป๐ฒ๐๐: Relational patterns matching can be used to express more complex conditions.
๐ก ๐ฅ๐ฒ๐น๐ฎ๐๐ถ๐ผ๐ป๐ฎ๐น ๐ฃ๐ฎ๐๐๐ฒ๐ฟ๐ป๐ ๐ ๐ฎ๐๐ฐ๐ต๐ถ๐ป๐ด is not always the best solution. Sometimes, it is simpler and more efficient to use the traditional way of checking if an expression matches a certain condition.
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐
โ ๐ฅ๐ฒ๐น๐ฎ๐๐ถ๐ผ๐ป๐ฎ๐น ๐ฃ๐ฎ๐๐๐ฒ๐ฟ๐ป๐ ๐ ๐ฎ๐๐ฐ๐ต๐ถ๐ป๐ด is a feature introduced in ๐# ๐ต that enhances the pattern matching capabilities of the language. Pattern matching is a way to compare values against patterns.
โ ๐ฅ๐ฒ๐น๐ฎ๐๐ถ๐ผ๐ป๐ฎ๐น ๐ฃ๐ฎ๐๐๐ฒ๐ฟ๐ป๐ ๐ ๐ฎ๐๐ฐ๐ต๐ถ๐ป๐ด specifically allows you to perform pattern matching based on relational comparisons, such as greater than, less than, greater than or equal to, and less than or equal to comparisons.
โ It is a ๐ณ๐๐ป๐ฐ๐๐ถ๐ผ๐ป๐ฎ๐น programming technique, which means that it focuses on the evaluation of expressions rather than the control flow of your code.
๐ฅ ๐๐ฑ๐๐ฎ๐ป๐๐ฎ๐ด๐ฒ๐ ๐ผ๐ณ ๐ฟ๐ฒ๐น๐ฎ๐๐ถ๐ผ๐ป๐ฎ๐น ๐ฝ๐ฎ๐๐๐ฒ๐ฟ๐ป๐ ๐บ๐ฎ๐๐ฐ๐ต๐ถ๐ป๐ด:
โพ๏ธ ๐๐ผ๐ป๐ฐ๐ถ๐๐ฒ๐ป๐ฒ๐๐: Relational patterns matching can be used to create more concise and readable code.
โพ๏ธ ๐๐ ๐ฝ๐ฟ๐ฒ๐๐๐ถ๐๐ฒ๐ป๐ฒ๐๐: Relational patterns matching can be used to express more complex conditions.
๐ก ๐ฅ๐ฒ๐น๐ฎ๐๐ถ๐ผ๐ป๐ฎ๐น ๐ฃ๐ฎ๐๐๐ฒ๐ฟ๐ป๐ ๐ ๐ฎ๐๐ฐ๐ต๐ถ๐ป๐ด is not always the best solution. Sometimes, it is simpler and more efficient to use the traditional way of checking if an expression matches a certain condition.
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐
โ๏ธ ๐จ๐๐ฒ '๐ ๐ถ๐ป๐๐' ๐ผ๐ฟ '๐ ๐ฎ๐
๐๐' ๐ถ๐ป๐๐๐ฒ๐ฎ๐ฑ ๐ผ๐ณ ๐ผ๐ฟ๐ฑ๐ฒ๐ฟ๐ถ๐ป๐ด ๐ฎ๐ป๐ฑ ๐๐ฎ๐ธ๐ถ๐ป๐ด '๐๐ถ๐ฟ๐๐' ๐ผ๐ฟ '๐๐ฎ๐๐'
โ LINQ ๐ ๐ถ๐ป๐๐ and ๐ ๐ฎ๐ ๐๐ are extension methods in C# that allow you to find the minimum or maximum element in a sequence based on a specified property. They were introduced in .๐ก๐๐ง ๐ฒ.
๐ก Simplify LINQ expression by Use ๐ ๐ถ๐ป๐๐ or ๐ ๐ฎ๐ ๐๐ instead of ordering and taking 'First' or 'Last'
๐ฅ ๐ง๐ต๐ฒ ๐ฎ๐ฑ๐๐ฎ๐ป๐๐ฎ๐ด๐ฒ๐ ๐ผ๐ณ ๐๐๐ถ๐ป๐ด ๐๐๐ก๐ค ๐ ๐ถ๐ป๐๐ ๐ฎ๐ป๐ฑ ๐ ๐ฎ๐ ๐๐:
โพ๏ธThey are more concise and easier to read.
โพ๏ธThey are more efficient, as they do not need to sort the entire sequence.
โพ๏ธThey can be used with any type of sequence, including sequences of objects.
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐
โ LINQ ๐ ๐ถ๐ป๐๐ and ๐ ๐ฎ๐ ๐๐ are extension methods in C# that allow you to find the minimum or maximum element in a sequence based on a specified property. They were introduced in .๐ก๐๐ง ๐ฒ.
๐ก Simplify LINQ expression by Use ๐ ๐ถ๐ป๐๐ or ๐ ๐ฎ๐ ๐๐ instead of ordering and taking 'First' or 'Last'
๐ฅ ๐ง๐ต๐ฒ ๐ฎ๐ฑ๐๐ฎ๐ป๐๐ฎ๐ด๐ฒ๐ ๐ผ๐ณ ๐๐๐ถ๐ป๐ด ๐๐๐ก๐ค ๐ ๐ถ๐ป๐๐ ๐ฎ๐ป๐ฑ ๐ ๐ฎ๐ ๐๐:
โพ๏ธThey are more concise and easier to read.
โพ๏ธThey are more efficient, as they do not need to sort the entire sequence.
โพ๏ธThey can be used with any type of sequence, including sequences of objects.
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐
โ๏ธ ๐ก๐๐น๐น ๐๐ผ๐ฎ๐น๐ฒ๐๐ฐ๐ถ๐ป๐ด ๐ข๐ฝ๐ฒ๐ฟ๐ฎ๐๐ผ๐ฟ
โ 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?
๐ง๐ต๐ฎ๐ป๐ธ ๐๐ผ๐ ๐ณ๐ผ๐ฟ ๐ฟ๐ฒ๐ฎ๐ฑ๐ถ๐ป๐ด ๐