Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Dictionary.GetValueOrDefault#14521

Closed
AlexRadch wants to merge 6 commits into
dotnet:masterfrom
AlexRadch:Dictionary-GetValueOrDefault
Closed

Dictionary.GetValueOrDefault#14521
AlexRadch wants to merge 6 commits into
dotnet:masterfrom
AlexRadch:Dictionary-GetValueOrDefault

Conversation

@AlexRadch
Copy link
Copy Markdown

With dictionaries of class-types it is often desirable and expected to return null for a non-existent key.
Close https://github.com/dotnet/corefx/issues/3482

{
public static class CollectionExtensions
{
public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Linq's extension methods throw ArgumentNullException when the source is null. I think we should do the same for these extension methods, throwing ArgumentNullException if the dictionary is null.

Copy link
Copy Markdown
Author

@AlexRadch AlexRadch Dec 14, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fixed this

public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue)
{
if (dictionary.ContainsKey(key))
return dictionary[key];
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going to lookup the key twice. Consider something like:

TValue value;
return dictionary.TryGetValue(key, out value) ? value : defaultValue;

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interface IDictionary does not have TryGetValue method

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@justinvp
Copy link
Copy Markdown
Contributor

Dictionary in the coreclr repo will need to be updated as well.

@justinvp
Copy link
Copy Markdown
Contributor

The APIs will need to be exposed in the contracts by adding them to src/System.Collections/ref/System.Collections.cs within #if netcoreapp11 (see other examples in that file).

There should also be tests added as part of this. The tests for the Dictionary<TKey, TValue> change won't work until the CoreCLR change has been merged and propagated.

@AlexRadch
Copy link
Copy Markdown
Author

AlexRadch commented Dec 15, 2016

@justinvp I tried expose API to ref, but after that project can not be compiled. I do not know how to compile it with new contract. Can you help me to compile it?

@ianhays
Copy link
Copy Markdown
Contributor

ianhays commented Dec 15, 2016

@AlexRadch this PR should be in coreclr. The Dictionary class in CoreFX isn't used for netcoreapp builds, it's only there for building UAP.

Sorry for the confusion about this. In the future you can figure out what we're actually taking from corefx and what we're taking from coreclr by looking at the csproj and seeing what TargetGroup the file is included under.

I'd suggest you just close this out and reopen it against the coreclr repo. Then, once that merges, you can open another PR in CoreFX adding the new methods to the ref file and adding tests.

@justinvp
Copy link
Copy Markdown
Contributor

@ianhays, the CollectionExtensions part of the change should still go in CoreFX. Once the Dictionary change in dotnet/coreclr#8641 is merged and propagated to CoreFX, would it make sense to continue with this PR which would: add CollectionExtensions, include the Dictionary change for UAP, add the new APIs to the contracts, and add tests?

@AlexRadch
Copy link
Copy Markdown
Author

@ianhays @justinvp thanks for answer.

@ianhays
Copy link
Copy Markdown
Contributor

ianhays commented Dec 15, 2016

Once the Dictionary change in dotnet/coreclr#8641 is merged and propagated to CoreFX

Thanks @justinvp, I didn't know there was already a coreclr PR. You're correct on the order of operations.

@justinvp I tried expose API to ref, but after that project can not be compiled. I do not know how to compile it with new contract. Can you help me to compile it?

It won't compile until you merge the coreclr PR and CoreFX is updated with a new version of mscorlib that contains your coreclr changes.

TValue value;
dictionary.TryGetValue(key, out value);
return value;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be implemented in terms of the other overload to prevent code duplication. Same for the IDictionary method.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ianhays I do not understand your suggestion.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You already did it. I was talking about doing this:

public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key) => dictionary.GetValueOrDefault(key, default(TValue));

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand your suggestion after wrote my comment and I changed code to remove duplication.

// This allows them to continue getting that behavior with minimal code delta. This is basically
// TryGetValue without the out param
internal TValue GetValueOrDefault(TKey key)
public TValue GetValueOrDefault(TKey key)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comments from the coreclr PR apply here as well.

Copy link
Copy Markdown
Contributor

@ianhays ianhays left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there tests for this? You should be able to use the same ones as TryGetValue.

I had a few comments, but it mostly looks good to me. Thanks Alex. We'll need to wait a few days to consume the coreclr changes after they merge.

@ianhays
Copy link
Copy Markdown
Contributor

ianhays commented Dec 19, 2016

Source changes LGTM once we have tests.

@danmoseley
Copy link
Copy Markdown
Member

@dotnet-bot test this (updated clr)

@danmoseley
Copy link
Copy Markdown
Member

Trying to trigger retest.

@karelz
Copy link
Copy Markdown
Member

karelz commented Jan 11, 2017

@AlexRadch do you plan to finish the work?

@karelz
Copy link
Copy Markdown
Member

karelz commented Jan 19, 2017

The PR seems to be abandoned for 1 month. Closing it for now.

@karelz karelz closed this Jan 19, 2017
@karelz karelz modified the milestone: 2.0.0 Jan 21, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants