C#

C#

By DeepSource

Redundant call to ToCharArray() when iterating a string CS-P1004
Performance
Autofix

The ToCharArray() returns a char array whose elements are the individual characters of the string on which this method is called. However, this call is particularly redundant within a foreach statement as foreach allows you to iterate through the types that implement IEnumerable or IEnumerable<T>, such as string in this case. Therefore, it is recommended that you get rid of this redundant call.

Consider reusing existing instances of StringBuilder CS-P1020
Performance

Instantiating a new instance of StringBuilder requires the initialization of the underneath buffer that holds the string contents. Creating a new instance in a loop may have an adverse performance impact. Instead, it is recommended that you initialize StringBuilder outside the loop and reuse it within the loop by clearing it when required.

Calling garbage collector manually does not necessarily improve performance CS-P1001
Performance

The .NET runtime ships with a GC (Garbage Collector) that is responsible for allocation and freeing up of memory as deemed necessary during an application's lifetime. It is responsible for automatically handling memory management-related tasks and preventing accidents such as memory leaks, accidental double frees, etc. Manually invoking the GC does not necessarily improve your application's performance and, in some cases, may even adversely impact the performance. If you wish to improve your application's performance, consider measures such as:

Consider using the appropriate overloaded method when searching for a single char CS-P1006
Performance
Autofix

Methods such as string.Contains and string.IndexOf allow you to search for an occurrence of either a single char or a substring within a string. If you'd like to search for an occurrence of a single char, it is recommended that you use the appropriate method that takes a char as a parameter rather than a string as the former approach is more performant and recommended.

Use ContainsKey() to check if a key exists in a Dictionary<T, K> CS-P1016
Performance
Autofix

If you wish to check if a key exists in a Dictionary, consider using the ContainsKey() that ideally has a complexity of O(1). Using the .Keys.Contains() deteriorates the performance as it has a complexity of O(n) where n = number of elements in your Dictionary.

Use Environment.ProcessId to fetch process ID instead of Process.GetCurrentProcess().Id CS-P1012
Performance
Autofix

You can use GetCurrentProcess().Id to access the running program's process ID. However, this is an expensive call as it first allocates a Process instance which then needs to be disposed, all just to get the running program's process ID. An efficient alternative is to just use the static field Environment.ProcessId.

Use Environment.ProcessPath to fetch process path instead of Process.GetCurrentProcess().MainModule.FileName CS-P1013
Performance
Autofix

You can use Process.GetCurrentProcess().MainModule.FileName to access the running program's path. However, this is an expensive call as it first allocates a Process instance which then needs to be disposed, all just to get the running program's path. An efficient alternative is to just use the static field Environment.ProcessPath.

Use Environment.CurrentManagedThreadId to fetch the thread ID instead of Thread.CurrentThread.ManagedThreadId CS-P1014
Performance
Autofix

You can use Thread.CurrentThread.ManagedThreadId to access the running program's path. However, an easier alternative is to just use the static field Environment.CurrentManagedThreadId that does just the same. It is simpler and easier to read and remember.

Unusual data type specified for enum CS-P1021
Performance

An enum by default uses int as an underlying data type. However, changing this to a type whose size is less than that of int's is likely an unnecessary optimization as such an optimization would not necessarily yield any performance improvements. Any performance improvements, if gained, however, are likely to be minute.

Consider reusing record objects that rely on const parameters CS-P1022
Performance

Records are structures that are extensively used in serialization and deserialization. However, if your instance of record takes in parameters that are class' const fields, consider reusing the same record instance instead of instantiating a new one.

Avoid chaining of index lookup and .Substring method CS-P1007
Performance

Index lookup methods such as IndexOf, LastIndexOf, IndexOfAny, and LastIndexOfAny return the index of the char depending on the arguments supplied. Chaining such calls to .Substring requires that a part of the string be selected and then the char be looked up. Instead, consider calling the index lookup methods directly and then subtracting the begin offset.

Avoid empty finalizers CS-P1000
Performance
Autofix

Finalizers, i.e., destructors, perform clean-up operations as an instance is picked up for garbage collection (GC). If a class has a finalizer defined, it is added to the Finalize queue, which is later processed by the GC when deemed appropriate. An empty finalizer adds unnecessary additional overhead to the GC since it does not perform effective clean-up operations. Therefore, it is suggested that you either remove the empty finalizer or add relevant clean-up operations.

Consider using Environment.ProcessId instead of Process.GetCurrentProcess().Id CS-P1002
Performance

Using Process.GetCurrentProcess().Id requires that an instance of Process be allocated to access the required Id. It then adds additional overhead, i.e., disposing of the Process instance. It is therefore suggested that you use the reliable and performant alternative Environment.ProcessId.

Consider making static readonly fields const CS-P1003
Performance

Expressions marked as static readonly do not require an object/instance of a class and can be accessed directly. Since they're marked as static, they cannot be modified outside a static constructor. If such fields exist in a class without a static constructor, it is recommended that you mark them as const since expressions marked as const are fully evaluated at the compile-time.

Consider using .TryGetValue to access elements in Dictionary CS-P1005
Performance

The .ContainsKey method allows you to check if a key exists in a Dictionary while the indexer, i.e. [] allows you to directly access the specified key's value. Using both of them means that you'd be effectively accessing the Dictionary twice. As an alternative, you can use .TryGetValue to get a value from a Dictionary that returns a bool depending on whether the key exists or not.

Consider rewriting chained .OrderBy() calls as .ThenBy() CS-P1008
Performance

The .OrderBy() method allows you to specify the criteria according to which the elements must be ordered and returns a new ordering. Everytime the .OrderBy() method is invoked, the previous ordering, if any, is lost, resulting in a wastage of resources. To preserve any previous ordering, rewrite subsequent .OrderBy() methods as .ThenBy().

Use Array.Empty<T>() to efficiently create empty arrays CS-P1009
Performance
Autofix

Using the new keyword lets you create an array with the length of your choice. However, memory allocation, no matter how big or small, comes at a cost. Instead, it is recommended that you use Array.Empty<T>() to create an empty array as it maintains a readonly static buffer internally, thereby essentially maintaining a single instance instead of multiple copies despite multiple invocations. Refer to the benchmarks mentioned in the references section below for additional info.

Rewrite virtual void Finalize() as ~Destructor() CS-P1010
Performance

Destructors, often represented as ~Foo() (where Foo = class name) are used to perform clean-up operations when being garbage collected. Such calls are translated to override void Finalize() automatically and contain further instructions to invoke the Finalize method recursively for all the instances in the inheritance chain to perform a full clean-up. It is therefore recommended that you let the compiler and runtime do the translation and that you not explicitly define virtual void Finalize(). Additionally, if you wish to perform clean-up operations such as closing file handles and database connections, it is recommended that you take a look at the IDisposable interface as Finalizers are invoked by the runtime when deemed appropriate.

Use the method overload that accepts Span<T> instead of T[] when possible to reduce allocations CS-P1011
Performance

Span<T> is a structure that is allocated on the stack rather than heap, thereby reducing the number of allocations during the program's lifetime which in return exerts less pressure on the GC. Since the method that you're trying to invoke has an overload that accepts Span<T>, it is therefore suggested that you use that overload and pass Span<T> rather than T[].

Passing an identity function to Select() is redundant CS-P1015
Performance

The Select() method from System.Linq transforms an IEnumerable<T>'s elements based on the lambda specified. An identity function is a function that returns the same element unchanged that was passed as its argument. Since such a function does nothing useful, passing it to Select() does not modify the elements and is just a redundant expression. It is recommended that you drop such redundant expressions.