Refresh

C# 12 Tip

1. 𝗨𝘀𝗲 𝗙𝗶𝗻𝗱 𝗶𝗻𝘀𝘁𝗲𝗮𝗱 𝗼𝗳 𝗙𝗶𝗿𝘀𝘁𝗢𝗿𝗗𝗲𝗳𝗮𝘂𝗹𝘁 𝘄𝗶𝘁𝗵 𝗰𝗼𝗹𝗹𝗲𝗰𝘁𝗶𝗼𝗻𝘀

✅ Both 𝗙𝗶𝗿𝘀𝘁𝗢𝗿𝗗𝗲𝗳𝗮𝘂𝗹𝘁 and 𝗙𝗶𝗻𝗱 are used to find the first element in a collection that meets a specific condition.

🐌 𝗙𝗶𝗿𝘀𝘁𝗢𝗿𝗗𝗲𝗳𝗮𝘂𝗹𝘁: Iterates through all elements until it finds a match, leading to slower performance for large collections.

🚀 𝗙𝗶𝗻𝗱: Can potentially be faster for in-memory collections (like List<T>) because it can potentially use direct indexing to locate the element.

✳ Both 𝗙𝗶𝗻𝗱 and 𝗙𝗶𝗿𝘀𝘁𝗢𝗿𝗗𝗲𝗳𝗮𝘂𝗹𝘁 return default values if no matching element is found in the collection.


2.  𝗖# 𝟭𝟮 𝗣𝗿𝗶𝗺𝗮𝗿𝘆 𝗖𝗼𝗻𝘀𝘁𝗿𝘂𝗰𝘁𝗼𝗿𝘀

✅ 𝗖# 𝟭𝟮 introduces 𝗽𝗿𝗶𝗺𝗮𝗿𝘆 𝗰𝗼𝗻𝘀𝘁𝗿𝘂𝗰𝘁𝗼𝗿𝘀, a concise syntax to declare constructors whose parameters are available anywhere in the body of the type.

𝗧𝗵𝗲 𝗺𝗼𝘀𝘁 𝗰𝗼𝗺𝗺𝗼𝗻 𝘂𝘀𝗲𝘀 𝗳𝗼𝗿 𝗮 𝗽𝗿𝗶𝗺𝗮𝗿𝘆 𝗰𝗼𝗻𝘀𝘁𝗿𝘂𝗰𝘁𝗼𝗿 𝗽𝗮𝗿𝗮𝗺𝗲𝘁𝗲𝗿 𝗮𝗿𝗲:
◾ As an argument to a base() constructor invocation.
◾ To initialize a member field or property.
◾ Referencing the constructor parameter in an instance member.

🔥 You can use the 𝗽𝗿𝗶𝗺𝗮𝗿𝘆 𝗰𝗼𝗻𝘀𝘁𝗿𝘂𝗰𝘁𝗼𝗿𝘀 as best suits your design. For classes and structs, primary constructor parameters are parameters to a constructor that must be invoked. You can use them to initialize properties. You can initialize fields. Those properties or fields can be immutable, or mutable. You can use them in methods.


3. ✔ 𝗣𝗿𝗲𝗳𝗲𝗿 𝗔𝘀𝗦𝗽𝗮𝗻 𝗼𝘃𝗲𝗿 𝗦𝘂𝗯𝘀𝘁𝗿𝗶𝗻𝗴 𝘁𝗼 𝗠𝗮𝘅𝗶𝗺𝗶𝘇𝗲 𝗽𝗲𝗿𝗳𝗼𝗿𝗺𝗮𝗻𝗰𝗲

🐌 The 𝗦𝘂𝗯𝘀𝘁𝗿𝗶𝗻𝗴 is a method that returns a new string that is a substring of the original string. It creates a new string object and copies the characters from the original string to the new substring. This can have an impact on performance and memory usage, especially when dealing with large strings or frequent substring operations.

🚀 The 𝗔𝘀𝗦𝗽𝗮𝗻 is a method that returns a ReadOnlySpan<char> from the original string. A ReadOnlySpan is a lightweight, stack allocated view over the data, and it doesn't create a new string object or copy the characters. This can lead to better performance and reduced memory overhead, especially in scenarios where you need to work with portions of a string without the need for actual string manipulation.

💡 Many APIs that accept strings also have overloads that accept a ReadOnlySpan<char> argument. When such overloads are available, you can improve performance by calling AsSpan instead of Substring.

✅ However, keep in mind that there are scenarios where using Substring might still be appropriate, such as when you need a copy of the substring.


4. 𝗧𝗵𝗿𝗲𝗲 𝗪𝗮𝘆𝘀 𝘁𝗼 𝗪𝗼𝗿𝗸 𝘄𝗶𝘁𝗵 𝗝𝗦𝗢𝗡

✅ JSON (JavaScript Object Notation) is a lightweight format for data exchange. There are several libraries available to work with JSON.

💡 𝗡𝗲𝘄𝘁𝗼𝗻𝘀𝗼𝗳𝘁.𝗝𝘀𝗼𝗻, also known as 𝗝𝘀𝗼𝗻.𝗡𝗘𝗧, the most popular JSON library. It’s Feature-rich, ideal for complex scenarios.

👍 𝗦𝘆𝘀𝘁𝗲𝗺.𝗧𝗲𝘅𝘁.𝗝𝘀𝗼𝗻 is a built-in JSON library. It’s fast and doesn’t use much computer memory. It’s perfect for modern .NET applications.

🔥 𝗡𝗲𝘁𝗝𝗦𝗢𝗡 is a lightweight JSON library. It’s faster than both Newtonsoft.Json and System.Text.Json. It’s not as widely known as other JSON libraries.

5. 𝗣𝗮𝗴𝗶𝗻𝗮𝘁𝗶𝗼𝗻 𝗶𝗻 𝗘𝗙 𝗖𝗼𝗿𝗲

✅ 𝗣𝗮𝗴𝗶𝗻𝗮𝘁𝗶𝗼𝗻 refers to the process of dividing a large dataset into smaller, more manageable pages of data. This is particularly useful when dealing with large result sets, as it allows for data to be retrieved and displayed in a user-friendly manner, typically through a user interface that lets users navigate between different pages of results.

💡 Implementing pagination with EF Core typically involves using the 𝗦𝗸𝗶𝗽 and 𝗧𝗮𝗸𝗲 methods to fetch a specific subset of records from the database.

🔥 The advantages include better performance due to reduced server load, an enhanced user experience with easier data navigation, and more efficient data handling on the client-side.

6. 𝗧𝗵𝗿𝗲𝗲 𝗪𝗮𝘆𝘀 𝗳𝗼𝗿 𝗰𝗵𝗲𝗰𝗸𝗶𝗻𝗴 𝘀𝘁𝗿𝗶𝗻𝗴𝘀

👍 𝗨𝘀𝗶𝗻𝗴 𝗦𝘁𝗮𝗿𝘁𝘀𝗪𝗶𝘁𝗵 𝗮𝗻𝗱 𝗘𝗻𝗱𝘀𝗪𝗶𝘁𝗵 𝗺𝗲𝘁𝗵𝗼𝗱𝘀:
The StartsWith and EndsWith methods provided by the String class. These methods check whether a string starts or ends with a specified character.

💡 𝗨𝘀𝗶𝗻𝗴 𝗜𝗻𝗱𝗲𝘅𝗲𝗿 𝗣𝗿𝗼𝗽𝗲𝗿𝘁𝘆 𝗮𝗻𝗱 ^ 𝗢𝗽𝗲𝗿𝗮𝘁𝗼𝗿:
The indexer property allows us to access a specific character in a string by its position. The ^ operator is used to indicate an index from the end of the string.

🔥 𝗨𝘀𝗶𝗻𝗴 𝗟𝗶𝘀𝘁 𝗣𝗮𝘁𝘁𝗲𝗿𝗻:
The List Pattern feature that was introduced in C# 11. This feature allows us to match an array or a list with a sequence of elements. The .. operator which called Slice Pattern indicates any number of elements in between the first and last element.

🤔 Which one do you prefer?


8. ✔ 𝗣𝗿𝗲𝗳𝗲𝗿 𝗧𝗮𝘀𝗸.𝗪𝗵𝗲𝗻𝗔𝗹𝗹 𝗼𝘃𝗲𝗿 𝗺𝘂𝗹𝘁𝗶𝗽𝗹𝗲 𝗮𝘄𝗮𝗶𝘁𝘀

✅ 𝗧𝗮𝘀𝗸.𝗪𝗵𝗲𝗻𝗔𝗹𝗹 is a method that allows you to await the completion of multiple asynchronous tasks concurrently. It's part of the System.Threading.Tasks namespace and is often used in scenarios where you want to wait for multiple asynchronous operations to complete without blocking the main thread.

🚀 Using 𝗧𝗮𝘀𝗸.𝗪𝗵𝗲𝗻𝗔𝗹𝗹 can lead to better performance in scenarios where you have multiple independent asynchronous operations that can be executed concurrently. Instead of awaiting each task one by one, you can use Task.WhenAll to wait for all of them simultaneously, thus potentially reducing the overall waiting time.

💡 Avoid using 𝗧𝗮𝘀𝗸.𝗪𝗵𝗲𝗻𝗔𝗹𝗹 in scenarios where tasks have complex dependencies, require specialized synchronization, have limited available resources, involve mostly synchronous I/O, need isolation of exceptions, or demand sequential execution. Additionally, exercise caution when using it on UI threads, and evaluate whether the benefits of concurrency outweigh the potential downsides in terms of performance and control.


9. ✔ 𝗨𝘀𝗲 𝗖𝗼𝗻𝘁𝗮𝗶𝗻𝘀 𝗶𝗻𝘀𝘁𝗲𝗮𝗱 𝗼𝗳 𝗔𝗻𝘆 𝗳𝗼𝗿 𝘀𝗶𝗺𝗽𝗹𝗲 𝗲𝗾𝘂𝗮𝗹𝗶𝘁𝘆 𝗰𝗵𝗲𝗰𝗸𝘀

🐌 𝗔𝗻𝘆 is a more general method that checks if any element in the collection satisfies a provided condition. The condition is represented as a lambda expression, which adds a level of overhead.

🚀 The 𝗖𝗼𝗻𝘁𝗮𝗶𝗻𝘀 method is simpler and more efficient when you're checking for the presence of a specific item in a collection. This is because Contains directly checks for the equality of each element to the specified value, which can be done very quickly, especially if the collection type has optimized this operation.

✅ The actual performance difference may be negligible unless you're working with large collections or performing the operation many times. The Any method is more flexible and can handle more complex conditions, but for simple equality checks, Contains is the better choice.

💡 This tip applies to the following collection types:
◾List<T> ◾HashSet<T> ◾SortedSet<T>


10. ✔𝗦𝘄𝗶𝘁𝗰𝗵 𝗘𝘅𝗽𝗿𝗲𝘀𝘀𝗶𝗼𝗻

🕯 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.


11. ✔ 𝗥𝗲𝗽𝗹𝗮𝗰𝗲 𝗶𝗳 𝘀𝘁𝗮𝘁𝗲𝗺𝗲𝗻𝘁 𝘄𝗶𝘁𝗵 𝗡𝘂𝗹𝗹 𝗖𝗼𝗻𝗱𝗶𝘁𝗶𝗼𝗻𝗮𝗹 𝗢𝗽𝗲𝗿𝗮𝘁𝗼𝗿

✅ The 𝗻𝘂𝗹𝗹 𝗰𝗼𝗻𝗱𝗶𝘁𝗶𝗼𝗻𝗮𝗹 𝗼𝗽𝗲𝗿𝗮𝘁𝗼𝗿, also known as the null propagation operator or the safe navigation operator, is a feature introduced in 𝗖# 𝟲.𝟬 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.

🔥 𝗔𝗱𝘃𝗮𝗻𝘁𝗮𝗴𝗲𝘀 𝗼𝗳 𝘂𝘀𝗶𝗻𝗴 𝘁𝗵𝗲 𝗻𝘂𝗹𝗹 𝗰𝗼𝗻𝗱𝗶𝘁𝗶𝗼𝗻𝗮𝗹 𝗼𝗽𝗲𝗿𝗮𝘁𝗼𝗿:
◾It can make your code more concise and readable.
◾It can help to avoid null-reference exceptions.
◾It can be used to chain together multiple member or element accesses, even if some of the members or elements may be null.


12. 𝗨𝘀𝗲 𝗘𝘅𝗶𝘀𝘁𝘀 𝗶𝗻𝘀𝘁𝗲𝗮𝗱 𝗼𝗳 𝗔𝗻𝘆 𝘄𝗶𝘁𝗵 𝗰𝗼𝗹𝗹𝗲𝗰𝘁𝗶𝗼𝗻𝘀

✅ 𝗘𝘅𝗶𝘀𝘁𝘀 is a method that is available on collections like List<T> and Array types. It checks whether an element that satisfies the condition exists in the list or array.

✅ 𝗔𝗻𝘆 is a LINQ method that works with any IEnumerable<T> (which includes arrays, lists, and other collection types). It checks whether any element in the IEnumerable<T> satisfies the condition.

🚀 𝗘𝘅𝗶𝘀𝘁𝘀 is generally faster than Any. This is because Exists can take advantage of the internal implementation of List<T> to perform the check more efficiently. Exists doesn't require the overhead of creating an enumerator that Any does.


13. 𝗥𝗲𝗹𝗮𝘁𝗶𝗼𝗻𝗮𝗹 𝗣𝗮𝘁𝘁𝗲𝗿𝗻𝘀 𝗠𝗮𝘁𝗰𝗵𝗶𝗻𝗴

✅ 𝗥𝗲𝗹𝗮𝘁𝗶𝗼𝗻𝗮𝗹 𝗣𝗮𝘁𝘁𝗲𝗿𝗻𝘀 𝗠𝗮𝘁𝗰𝗵𝗶𝗻𝗴 is a feature introduced in 𝗖# 𝟵 that enhances the pattern matching capabilities of the language. Pattern matching is a way to compare values against patterns.

✅ 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.


14.  𝗦𝗶𝗺𝗽𝗹𝗶𝗳𝘆 𝗰𝗼𝘂𝗻𝘁𝗶𝗻𝗴 𝘄𝗶𝘁𝗵 𝗖𝗼𝘂𝗻𝘁𝗕𝘆

🚀 𝗖𝗼𝘂𝗻𝘁𝗕𝘆 is a new method in .NET 9 that simplifies counting items in a collection.

🐌 Before the CountBy method, developers would group elements using 𝗚𝗿𝗼𝘂𝗽𝗕𝘆 and then count each group with 𝗦𝗲𝗹𝗲𝗰𝘁 and 𝗖𝗼𝘂𝗻𝘁. This was a more complex way to achieve the same result.

🔥 𝗖𝗼𝘂𝗻𝘁𝗕𝘆 offers a simplified approach to counting elements, making code more readable and reducing complexity. It also improves efficiency by minimizing the steps needed for counting in collections.


15. 𝗨𝘀𝗲 𝗿𝗲𝗰𝗼𝗿𝗱𝘀 𝗳𝗼𝗿 𝗗𝗧𝗢𝘀

✅ 𝗥𝗲𝗰𝗼𝗿𝗱𝘀 are a feature introduced in 𝗖# 𝟵.𝟬 that allows you to create simple, immutable data types. They are particularly useful for representing 𝗗𝗧𝗢𝘀 (Data Transfer Objects) because they provide a concise syntax for defining classes that are primarily used to transfer data between layers of an application, such as between the business logic layer and the presentation layer.

✅ 𝗥𝗲𝗰𝗼𝗿𝗱𝘀 are best suited for simple data structures, and they are not meant to replace classes for all scenarios. For more complex types with behavior, you may still want to use regular classes or other features provided by C#.

🔥 𝗥𝗲𝗰𝗼𝗿𝗱𝘀 are an excellent choice for creating 𝗗𝗧𝗢𝘀 due to their simplicity, immutability, and concise syntax, which helps in writing clean and maintainable code.


16. 𝗦𝘁𝗿𝗶𝗻𝗴𝘀 𝘀𝗵𝗼𝘂𝗹𝗱 𝗻𝗼𝘁 𝗯𝗲 𝗰𝗼𝗻𝗰𝗮𝘁𝗲𝗻𝗮𝘁𝗲𝗱 𝘂𝘀𝗶𝗻𝗴 '+' 𝗶𝗻 𝗮 𝗹𝗼𝗼𝗽

🐌 Strings are immutable, which means that once a string object is created, it cannot be modified. When you concatenate strings using the '+' 𝗼𝗽𝗲𝗿𝗮𝘁𝗼𝗿 in a loop, a new string object is created at each iteration, and the previous objects are discarded. This can lead to performance issues, especially when dealing with large strings or a large number of iterations.

🚀 A more efficient approach to string concatenation in C# is to use the 𝗦𝘁𝗿𝗶𝗻𝗴𝗕𝘂𝗶𝗹𝗱𝗲𝗿 𝗰𝗹𝗮𝘀𝘀, which is designed for efficiently building strings in a loop. StringBuilder allows you to append strings without creating new objects each time, which leads to better performance.

💡 𝗦𝘁𝗿𝗶𝗻𝗴𝗕𝘂𝗶𝗹𝗱𝗲𝗿 is more useful when dealing with large strings or a large number of iterations and when we have an unknown amount of strings.

🔥 By using 𝗦𝘁𝗿𝗶𝗻𝗴𝗕𝘂𝗶𝗹𝗱𝗲𝗿, you can significantly reduce memory allocations and improve the performance of your code when you need to concatenate strings in a loop. It is a best practice to use StringBuilder when working with dynamic string building operations.


17.  𝗧𝗵𝗿𝗲𝗲 𝘄𝗮𝘆𝘀 𝘁𝗼 𝗖𝗵𝗲𝗰𝗸 𝗳𝗼𝗿 𝗻𝗼𝘁 𝗻𝘂𝗹𝗹

💡 𝗶𝗳 (𝘀𝘁𝘂𝗱𝗲𝗻𝘁 != 𝗻𝘂𝗹𝗹) { }
This is the traditional way of checking for not null. It can be overloaded by the type of the object. This means that some types may define their own logic for comparing with null, which may not be what you expect.

👍 𝗶𝗳 (𝘀𝘁𝘂𝗱𝗲𝗻𝘁 𝗶𝘀 𝗻𝗼𝘁 𝗻𝘂𝗹𝗹) { }
Introduced in C# 9.0, this syntax provides a more readable way of checking for not null compared to the traditional approach.

🔥 𝗶𝗳 (𝘀𝘁𝘂𝗱𝗲𝗻𝘁 𝗶𝘀 {}) { }
This is another way introduced in C# 8.0 to perform a not null check.



18.  𝗔𝗣𝗜 𝗩𝗲𝗿𝘀𝗶𝗼𝗻𝗶𝗻𝗴

✅ When developing an API, it's crucial to manage changes and updates in a way that doesn't disrupt existing clients. 𝗔𝗣𝗜 𝘃𝗲𝗿𝘀𝗶𝗼𝗻𝗶𝗻𝗴 allows you to introduce new features and improvements while maintaining support for older versions.

💻 Imagine an API that provides access to a list of items. Initially (version 1.0), clients simply need to retrieve a list of all items. Later, version 2.0 introduces the ability to sort items by creation date. We need to implement API versioning to accommodate both versions seamlessly.

🔥 This approach allows clients to continue using the older version while new clients can opt for the latest features.


19. 𝗘𝘅𝗰𝗲𝗽𝘁𝗶𝗼𝗻 𝘃𝘀 𝗥𝗲𝘀𝘂𝗹𝘁 𝗣𝗮𝘁𝘁𝗲𝗿𝗻

✅ 𝗘𝘅𝗰𝗲𝗽𝘁𝗶𝗼𝗻𝘀 are special objects that represent an error or an unexpected event that occurs during the execution of a program. When an exception is thrown, it propagates up the call stack until it is caught by an appropriate catch block.

✅ 𝗥𝗲𝘀𝘂𝗹𝘁 𝗣𝗮𝘁𝘁𝗲𝗿𝗻 offers an alternative approach. Instead of throwing exceptions, methods return a result object. This object encapsulates either the successful result of the operation or an error message.

💡 𝗘𝘅𝗰𝗲𝗽𝘁𝗶𝗼𝗻𝘀 are more suitable for handling errors that are unexpected and outside the normal flow of the program.

💡 𝗥𝗲𝘀𝘂𝗹𝘁 𝗣𝗮𝘁𝘁𝗲𝗿𝗻 can be more appropriate for expected errors or when you want to avoid the overhead of exceptions.


20. 𝗘𝗙 𝗖𝗼𝗿𝗲 𝟳 𝗕𝘂𝗹𝗸 𝗗𝗲𝗹𝗲𝘁𝗲

🐌 𝗕𝗲𝗳𝗼𝗿𝗲 EF Core 7, deleting data involved looping through entities, marking them for removal, and finally saving changes. This approach translates to multiple database roundtrips, impacting performance, especially for large datasets.

🚀 EF Core 7 introduces 𝗕𝘂𝗹𝗸 𝗗𝗲𝗹𝗲𝘁𝗲 as a powerful new feature for deleting data. This new method simplifies the deletion process, making it 𝗺𝗼𝗿𝗲 𝗲𝗳𝗳𝗶𝗰𝗶𝗲𝗻𝘁 and less resource-intensive.

🔥EF Core 𝗕𝘂𝗹𝗸 𝗗𝗲𝗹𝗲𝘁𝗲 offers a significant performance improvement for deleting large datasets in your applications.


Author : JALAL AIZEBDA (https://www.linkedin.com/in/jalal-alzebda/)

Đăng nhận xét

Mới hơn Cũ hơn