If you use DeepSource for your C# projects, here’s some excellent news: in the latest release of DeepSource Cloud and Enterprise Server, we’ve added 32 new checks in our C# Analyzer for detecting more performance issues, bug risks and antipatterns.
Here’s a preview of some of the notable checks. Scroll down to the bottom of this post to see the complete list of all new checks!
(CS-P1016) Use ContainsKey() to check if a key exists in a Dictionary<T, K>
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
.
Bad practice:
if (dict.Keys.Contains(key))
{
// ...
}
Recommended:
if (dict.ContainsKey(key))
{
// ...
}
(CS-W1044) Lock is obtained on an entity that does not guarantee reliable mutual exclusion
Microsoft guidelines specifically state that lock's should not be obtained on
this,
System. Type’s, and string
instances. Doing so may cause deadlock or lock contention, thereby affecting your application’s execution and reliability. It is generally recommended that you dedicate a private
readonly
object
solely for locking.
Bad practice:
lock(this)
{
// ...
}
Recommended:
// _lockObj is an `object` that is class' private read-only member.
lock(_lockObj)
{
// ...
}
(CS-W1047) An async method should have at least a single awaitable
A method with an async
modifier indicates that it involves asynchronous work. Not having any await
expressions inside the method makes the async
modifier redundant, and the method proceeds synchronously. Consider adding appropriate await
expressions or dropping the async
modifier.
Explore all new static analysis checks:
- (CS-P1012) Use Environment.ProcessId to fetch process ID instead of Process.GetCurrentProcess().Id
- (CS-P1013) Use Environment.ProcessPath to fetch process path instead of Process.GetCurrentProcess().MainModule.FileName
- (CS-P1014) Use Environment.CurrentManagedThreadId to fetch the thread ID instead of Thread.CurrentThread.ManagedThreadId
- (CS-P1015) Passing an identity function to Select() is redundant
- (CS-P1016) Use ContainsKey() to check if a key exists in a Dictionary<T, K>
- (CS-P1017) Consider using more appropriate overload StringBuilder.Append(char)
- (CS-R1071) Consider using the constants from the Math class
- (CS-R1072) You can drop the lower bound in a range expression if is zero
- (CS-R1073) Methods that deal with async should have their names suffixed with Async
- (CS-R1074) DefaultParameterValue attribute is redundant when parameter is not marked as Optional
- (CS-R1075) Attribute suffix is redundant when using an attribute
- (CS-R1076) Use underscores to make long numeric literals readable
- (CS-R1077) Rewrite new System.Type[0] as Type.EmptyTypes
- (CS-R1078) abstract classes with only abstract methods should be declared as interfaces
- (CS-R1079) Replace string.Compare() with string.Equals()
- (CS-R1080) Reserving a member in an enum provides no benefit
- (CS-R1081) Consider using ThrowIfCancellation() where possible
- (CS-R1082) Reserved Exception being thrown
- (CS-W1042) Using negative array indices results in IndexOutOfRangeException
- (CS-W1043) Exceptions that are created must be used
- (CS-W1044) Lock is obtained on an entity that does not guarantee reliable mutual exclusion
- (CS-W1045) DefaultParameterValue must be used instead of DefaultValue when Optional attribute is specified
- (CS-W1046) Lock is obtained on a public object
- (CS-W1047) An async method should have at least a single awaitable
- (CS-W1048) GetHashCode() relies on a mutable entity
- (CS-W1049) enum marked with Flags attribute is missing required initialization
- (CS-W1050) StringBuilder is initialized with an invalid argument
- (CS-W1051) Number of elements passed instead of buffer length
- (CS-W1052) Do not declare finalizers for types derived from MemoryManager
- (CS-W1053) Value types should not be compared using object.ReferenceEquals()
- (CS-W1054) Dictionary<T, K> has duplicate key(s) in its initializer
- (CS-W1055) Argument passed to Enum.HasFlag should be same as the type on which it is being invoked