-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prefer Dictionary.Remove(key, out value) over Dictionary.this[key], followed by Dictionary.Remove(key) #33800
Comments
Estimates:
|
This is closely related to #33797 Suggested severity: Info // Before
public void RemoveValue(Dictionary<string, int> data, string key)
{
if (data.ContainsKey(key))
{
// Dictionary.ContainsKey<K, V(key),
// followed by Dictionary<K, V.this[key],
// followed by Dictionary<K, V>.Remove(key) can be combined into a single Remove call,
// using the overload accepting out TValue value.
Foo(data[key]);
data.Remove(key);
}
}
// After
public void RemoveValue(Dictionary<string, int> data, string key)
{
if (data.Remove(key, out int value))
{
Foo(value);
}
} Applying the below example in the analyzer might be more complicated: // Before
public void RemoveValue(Dictionary<string, int> data, string key)
{
if (data.ContainsKey(key))
{
int x = data[key];
data.Remove(key);
Foo(x);
}
}
// After
public void RemoveValue(Dictionary<string, int> data, string key)
{
if (data.Remove(key, out int value))
{
Foo(value);
}
} We should also consider the case where the data is used multiple times, and when there's unrelated code in the way: // Before
public void RemoveValue(Dictionary<string, int> data, string key)
{
if (data.ContainsKey(key))
{
Foo(data[key]);
UnrelatedMethodCall();
Bar(data[key]);
data.Remove(key);
}
}
// After
public void RemoveValue(Dictionary<string, int> data, string key)
{
if (data.Remove(key, out int value))
{
Foo(value);
UnrelatedMethodCall();
Bar(value);
}
} |
This comment has been minimized.
This comment has been minimized.
We came up with a lot of cases where the fixer can cause surprising functional changes, so this really only applies when there's an indexer followed by a call to Remove with no other method calls in between (because any method call could have modified the dictionary). As a specific example, in #33800 (comment) if The case of Conclusion: If we find a dictionary call to TryGetValue that is immediately followed by a call to Remove (and the dictionary and the key are both simple variable or parameter expressions) then suggest collapsing them to Remove(key, out T). ("immediate" definitely means that there are no method calls or delegate invocations between those two expressions)
|
@buyaa-n may I have this assigned to me? Thanks. |
Thank you @steveberdy, sorry for the delayed response, it is assigned to you now, JFYI there are several analyzer proposals for dictionary, their implementations preferred to be written in one place (with different diagnostic ID when needed). I see only one of them merged into repo please try to add your implementation to that |
I'm sorry. I don't really have time to make this analyzer. I've unassigned myself. |
Dictionary.ContainsKey<K, V(key)
, followed byDictionary<K, V.this[key]
, followed byDictionary<K, V>.Remove(key)
can be combined into a singleRemove
call, using the overload acceptingout TValue value
.Category: Performance
The text was updated successfully, but these errors were encountered: