Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

TryAdd exposure/implementation #16642

Merged
merged 3 commits into from
Mar 12, 2017
Merged

Conversation

jamesqo
Copy link
Contributor

@jamesqo jamesqo commented Mar 3, 2017

This is the matching PR for dotnet/coreclr#9923.
Fixes #1942

/cc @stephentoub, @ianhays, @safern, @danmosemsft

@ahsonkhan
Copy link
Member

@jamesqo, would you have to add it in coreclr as well? Or maybe just add an ApiCompatBaseline.txt (example: https://github.com/dotnet/corefx/blob/master/src/System.IO/src/ApiCompatBaseline.txt).

https://github.com/dotnet/coreclr/blob/68f72dd2587c3365a9fe74d1991f93612c3bc62a/src/mscorlib/src/System/Collections/Generic/Dictionary.cs

From CI:
D:\j\workspace\windows_nt_re---37265eab\Tools\ApiCompat.targets(53,5): error : MembersMustExist : Member 'System.Collections.Generic.Dictionary<TKey, TValue>.TryAdd(TKey, TValue)' does not exist in the implementation but it does exist in the contract. [D:\j\workspace\windows_nt_re---37265eab\src\System.Collections\src\System.Collections.csproj]
16:49:53 D:\j\workspace\windows_nt_re---37265eab\Tools\ApiCompat.targets(67,5): error : ApiCompat failed for 'D:\j\workspace\windows_nt_re---37265eab\bin\Windows_NT.AnyCPU.Release\System.Collections\netcoreapp\System.Collections.dll' [D:\j\workspace\windows_nt_re---37265eab\src\System.Collections\src\System.Collections.csproj]

@jamesqo
Copy link
Contributor Author

jamesqo commented Mar 3, 2017

@ahsonkhan I already made such a PR at dotnet/coreclr#9923; @danmosemsft wanted me to submit the matching tests in corefx before the coreclr implementation was merged. This PR will fail CI until that is merged.

@ahsonkhan
Copy link
Member

Got it. Thanks for clarifying :)

@karelz
Copy link
Member

karelz commented Mar 3, 2017

@jamesqo I added "Fixes #1942" to top post to enable auto-closing upon merge. Please shout out if it is wrong.

@TylerBrinkley
Copy link

Just curious, where does the XML documentation go for this new method?

Copy link
Member

@safern safern left a comment

Choose a reason for hiding this comment

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

LGTM. When we ingest the new coreclr with your changes you'll need to update the uapaot baseline file so that you don't get any failures in CI in the Build for all configurations.

You can do that by running:

msbuild src\System.Collections\src\System.Collections.csproj /p:BaselineAllApiCompatError=true /p:TargetGroup=uapaot

Thanks @jamesqo

@@ -33,5 +65,4 @@ public void Dictionary_Generic_Constructor_IEnumerable_IEqualityComparer(int cou
Assert.Equal(collection, copied);
}
}

}
Copy link
Member

Choose a reason for hiding this comment

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

nit: end of line

@jamesqo
Copy link
Contributor Author

jamesqo commented Mar 3, 2017

@TylerBrinkley

Just curious, where does the XML documentation go for this new method?

I'm not sure because I don't work at Microsoft. @karelz Would you know?

@karelz
Copy link
Member

karelz commented Mar 3, 2017

@TylerBrinkley do you mean /// comments docs?

@TylerBrinkley
Copy link

@karelz yes.

@karelz
Copy link
Member

karelz commented Mar 3, 2017

I poked at the topic in December. The story is not 100% clear yet (or rather I didn't quite like the story I heard and I plan to poke at it more ;-)).
There is repo for API docs - for all .NET platforms. How it is going to be correlated with /// comments in CoreFX repo is not yet finalized (One time sync or continuous sync? One way or both ways?).
I expect the discussion to restart by end of March (some prereq docs tooling will be in place by then).

So, that's where we are. Does it help? Do you have any immediate concerns or questions?

@TylerBrinkley
Copy link

@karelz, does that mean new APIs provided in .NET Core implemented in CoreCLR repo will not have XML comments documentation for the time being as those APIs are not in Net FX or Net Standard?

@karelz
Copy link
Member

karelz commented Mar 3, 2017

@TylerBrinkley I assume that at certain point (before shipping) we will create the documentation and also add it into IntelliSense.
It is not clear when it will happen and what will be the source of the IntelliSense docs (/// comments in source code, pre-populated from Desktop? Or the full API documentation in the docs repo?)

@danmoseley
Copy link
Member

I merged the implementation so we should be able to merge this in a day or so if it gets okayed

TKey key = CreateTKey(seed: count);
TValue value = dictionary.ContainsKey(key) ? dictionary[key] : default(TValue);
int originalCount = dictionary.Count;
bool alreadyContainsKey = dictionary.ContainsKey(key);
Copy link
Member

Choose a reason for hiding this comment

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

Why call ContainsKey(key) twice?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Now that GetValueOrDefault is in I no longer have to 😄

Copy link
Member

Choose a reason for hiding this comment

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

What does it have to do with GetValueOrDefault? Why did you ever need to call it twice?

Copy link
Member

Choose a reason for hiding this comment

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

You could do:

bool alreadyContainsKey = dictionary.ContainsKey(key);
TValue value = alreadyContainsKey ? dictionary[key] : default(TValue);
...
Assert.Equal(!alreadyContainsKey, dictionary.TryAdd(key, default(TValue)));

I'm with @stephentoub that there is no need in calling ContainsKey(key) twice.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@stephentoub

What does it have to do with GetValueOrDefault?

TValue value = dictionary.GetValueOrDefault(key)

Why did you ever need to call it twice?

I didn't think it mattered because this is test code. Are you concerned about code duplication in calling the method twice?

Copy link
Member

Choose a reason for hiding this comment

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

Are you concerned about code duplication in calling the method twice?

That it's confusing seeing it called twice when it's not necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@stephentoub Ok. Will try to keep in mind for later PRs

Assert.Equal(alreadyContainsKey ? originalCount : originalCount + 1, dictionary.Count);
Assert.Equal(dictionary[key], value);

if (!dictionary.Any())
Copy link
Member

Choose a reason for hiding this comment

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

In what situation will Any here return false?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Was a logical mistake on my part. Updated

return;
}

// It's unlikely that randomly generated data will already be in the dictionary,
Copy link
Member

Choose a reason for hiding this comment

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

I don't understand this comment... we already added key to the dictionary, so don't we know it's in there?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea, I should have thought of simply using the key that was added instead of finding a new key.

@danmoseley
Copy link
Member

As an aside @jamesqo if you want you could follow up with issue(s) for places you believe it would be worthwhile for us to start using this API.

@safern
Copy link
Member

safern commented Mar 7, 2017

Coreclr should now be updated to have your changes. So you can move forward on updating this one @jamesqo

@jamesqo
Copy link
Contributor Author

jamesqo commented Mar 7, 2017

@safern I am busy as of late, so I might not have time to respond to @stephentoub's feedback and fix the conflicts for a day or so.

@safern
Copy link
Member

safern commented Mar 8, 2017

@jamesqo the failures in CI are because the new API is not implemented in uap yet but it is in the contract. To fix that you need to do a baseline by running:
msbuild src\System.Collections\src\System.Collections.csproj /p:BaselineAllApiCompatError=true /p:TargetGroup=uapaot

and update the PR with the changes to the ApiCompatBaseline.uapaot.txt file.

@jamesqo
Copy link
Contributor Author

jamesqo commented Mar 8, 2017

@safern Will the failures be fixed if I submit a PR to the corert Dictionary?

@safern
Copy link
Member

safern commented Mar 8, 2017

Will the failures be fixed if I submit a PR to the corert Dictionary?

@jamesqo I'm not sure about that.

cc: @joperezr that can answer that.

@danmoseley
Copy link
Member

I think the answer is yes please do, but meantime update the baseline to unblock this PR.

@safern
Copy link
Member

safern commented Mar 8, 2017

+1.

@jamesqo please update the baseline so that we can unblock this PR and not wait to another PR in other repo and when you do the PR in CoreRT and it is ingested then we can update the baseline.

@jamesqo
Copy link
Contributor Author

jamesqo commented Mar 8, 2017

@danmosemsft I have already submitted a corert PR, actually: dotnet/corert#2926 How long does it take for the corert build to get updated? (/cc @jkotas) It'd be preferable to avoid adding more changes and submitting another PR to delete them later.

@jamesqo
Copy link
Contributor Author

jamesqo commented Mar 8, 2017

@safern You posted just before I did... how long does it take for the corert build to update? @jkotas usually merges the corert PRs really quickly because they're straight ports from coreclr, so I don't think this should block on that.

@danmoseley
Copy link
Member

@jamesqo after commit to CoreRT I believe they have to get ported to our internal "Project N" repo (where we do UWP runtime work) after which a bot puts up a PR like #16866

The baselines don't trigger an error if they have unnecessary lines, so there'll be no need to remove the excess entries later -- it will happen sooner or later -- and that's why we don't generally wait for such codeflow.

@joperezr
Copy link
Member

joperezr commented Mar 9, 2017

Will the failures be fixed if I submit a PR to the corert Dictionary?

Seems like it has been answered already, but you do want to update the baseline as part of this PR since even if you have the corert change merged, it will take some time (usually around a day) for ProjectN to produce a new Targeting pack and then for us to ingest it. Once we do that, we can update the baseline that you will change here.

TKey key = CreateTKey(seed: count);
TValue value = dictionary.GetValueOrDefault(key);
int originalCount = dictionary.Count;
bool alreadyContainsKey = dictionary.ContainsKey(key);
Copy link
Member

Choose a reason for hiding this comment

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

In what situation will this already contain the key? And isn't / shouldn't this be deterministic? Seems like the test should either assert that it contains the key or assert that it doesn't, based on the test's construction, rather than having to account for the possibility that it may or may not.

Even if you can't predict whether GenericIDictionaryFactory(count) will include the relevant key, we can still set up the test to ensure the key isn't there, e.g.

 var dictionary = (Dictionary<TKey, TValue>)GenericIDictionaryFactory(count); 
TKey key = CreateTKey(seed: count);
dictionary.Remove(key);
int originalCount = dictionary.Count;

TValue value = CreateTValue(seed: count);
Assert.True(dictionary.TryAdd(key, value));
Assert.Equal(originalCount + 1, dictionary.Count);
Assert.Equal(dictionary[key], value);

Assert.False(dictionary.TryAdd(key, default(TValue)));
Assert.Equal(originalCount + 1, dictionary.Count);
Assert.Equal(dictionary[key], value);

Copy link
Contributor Author

@jamesqo jamesqo Mar 12, 2017

Choose a reason for hiding this comment

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

You're right, it's probably not wise to have code that we're unsure will run floating around. Updated.

@stephentoub
Copy link
Member

LGTM. Thanks, @jamesqo.

@stephentoub stephentoub merged commit fa66c2e into dotnet:master Mar 12, 2017
@jamesqo jamesqo deleted the try.add.tests branch March 12, 2017 23:48
@karelz karelz modified the milestone: 2.0.0 Mar 15, 2017
picenka21 pushed a commit to picenka21/runtime that referenced this pull request Feb 18, 2022
* Exposure/implementation of Dictionary.TryAdd


Commit migrated from dotnet/corefx@fa66c2e
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.

10 participants