-
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
Replace Dictionary<,>.Keys.Contains with ContainsKey #35343
Comments
@jeffhandley @terrajobst want to move this proposal to runtime repo under your radar? |
I can take care of this implementation if you wish. I am wondering if we could somehow improve the banned API analyzer to allow catching such cases, basically you would want to forbid a specific method call in some specific context... |
In this case I think it would be enough to set the default diagnostic level to warning. |
@drewnoakes Do you think there are cases where it would make sense to call Tagging @mavasani for a second opinion. |
The banned API analyzer tends to be for banning APIs that are specific to a given code base. I don't think any code base has a use case for calling either of those methods. It may be possible to ship a framework-specific analyzer that's based on the banned API analyzer and bundles a known set of APIs, such as these. |
@drewnoakes My idea behind the use of the "Banned API" analyzer was to provide a way where we won't have to implement a new analyzer for each new member call we want to prevent. At the same time, the code in itself is pretty easy to write so there might be no point in having an infrastructure in place. |
@drewnoakes @mavasani Do you think that's better to report only on specific dictionary instances or also on the interface? Reporting also on the interface might catch more cases but could potentially lead to FP for custom implementations of the dictionary. I think the risk is pretty low so I would be in favor of catching everything that implements |
In addition to my previous comment, I am wondering if we should extend the rule to also cover |
@Evangelink This issue likely needs to be moved to https://github.com/dotnet/runtime with code-analyzer label and would need an approval on the design and/or implementation. @jeffhandley @bartonjs @stephentoub Can one of you please port this issue OR give an approval on the proposal here? |
I couldn't figure out the best area label to add to this issue. Please help me learn by adding exactly one area label. |
Sorry for the rush on implementing something! To be honest, I am a little lost with which issue is going where. As an external user, it feels more natural to have all of the analyzers in one place instead of having some in vs-threading some here, some in roslyn and others in roslyn-analyzers. Just my 2 cents. |
Tagging subscribers to this area: @eiriktsarpalis |
It's a reasonable suggestion in the Performance category. Because Dictionary's KeyCollection and ValueCollection types are lazy, there's not a whole lot of perf difference from the concrete type. The constructors just save a reference to the dictionary and the Contains methods forward to ContainsKey/ContainsValue (as appropriate). dict.Keys.Contains(foo); is roughtly equivalent to new object();
dict.ContainsKey(foo); though the latter example does need to work in two more dereference/invocations to add the extra couple of CPU cycles to the mix. Is there a good way to avoid hard-coding specific dictionary types here?
It becomes a lot more valuable when it's through the interfaces, since the Contains method would likely be the item-walking version from The trickiest case is probably this helper method: private static bool IsRelevant<T>(T candidate, IReadOnlyDictionary<string, T> context)
{
return context.Values.Contains(candidate);
} since it involves an analysis with a partially bound generic (it's probably not really any trickier than a concrete example, but generic type parameter symbols may have some interesting quirks to them in the symbol tree). This would probably be an IDE suggestion that we may kick up to a bigger warning via TFM opt-in. |
I would like to have this assigned to me. I just completed my work on this analyzer including the code fix provider. One flaw still unadressed is the fact that only Dictionary<T,K> has a ContainsValue method, the interfaces do not. I would suggest taking the simple route and only apply ContainsValue if we know the member which is accessed is a Dictionary<T,K>. This is the way I implemented it. |
@NewellClark thanks for starting working on this. I'm trying to assign to you but I can't for some reason, but consider it yours. @Mrnikbobjeff apologies for not assigning this to you when you requested it, but your offer is appreciated. We have many more analyzers marked as up-for-grabs and would love to get your help on those others too. |
@NewellClark We figured out why we cannot assign this to you. You must comment on the issue before you show up in the assignees list. |
@jeffhandley Gotcha. |
Can this be closed (dotnet/roslyn-analyzers#4687)? |
Yes, closing |
This is a proposal for a new analyzer/codefix for:
I found this code in some design-time build targets today.
EDIT I'd previously incorrectly stated that the former form was O(N), but
System.Linq.Enumerable.Contains
does type test forICollection<>
and delegate toICollection<>.Contains
, which is also O(1). There is some overhead associated with that however, which could be avoided.The text was updated successfully, but these errors were encountered: