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

Implement Enumerable.ToHashSet()#13726

Merged
VSadov merged 1 commit intodotnet:masterfrom
JonHanna:to_hash_set
Nov 28, 2016
Merged

Implement Enumerable.ToHashSet()#13726
VSadov merged 1 commit intodotnet:masterfrom
JonHanna:to_hash_set

Conversation

@JonHanna
Copy link
Copy Markdown
Contributor

Closes #2323

A straight-forward implementation, forgoing any optimisations. HashSet's constructor already has some for some cases, and others could be wasteful unless not just the number of elements, but the number of elements that are distinct in terms of the equality comparer can be predicted.

Comment thread src/System.Linq/dir.props
<Import Project="..\dir.props" />
<PropertyGroup>
<AssemblyVersion>4.1.2.0</AssemblyVersion>
<AssemblyVersion>4.2.0.0</AssemblyVersion>
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I gather it's ++minor on additions of public members. Am I correct?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yup

Comment thread src/System.Linq/ref/System.Linq.cs Outdated
public static System.Collections.Generic.Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(this System.Collections.Generic.IEnumerable<TSource> source, System.Func<TSource, TKey> keySelector, System.Func<TSource, TElement> elementSelector) { throw null; }
public static System.Collections.Generic.Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(this System.Collections.Generic.IEnumerable<TSource> source, System.Func<TSource, TKey> keySelector, System.Func<TSource, TElement> elementSelector, System.Collections.Generic.IEqualityComparer<TKey> comparer) { throw null; }
public static System.Collections.Generic.HashSet<TElement> ToHashSet<TElement>(this System.Collections.Generic.IEnumerable<TElement> source) { throw null; }
public static System.Collections.Generic.HashSet<TElement> ToHashSet<TElement>(this System.Collections.Generic.IEnumerable<TElement> source, System.Collections.Generic.IEqualityComparer<TElement> comparer) { throw null; }
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@weshaggard, does any specialization need to be done for netstandard vs netcoreapp?

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.

We had been surrounding new APIs with #if netcoreapp11 in the ref assemblies and tests were separated out into conditionally included _Foo_Tests.netcoreapp1.1.cs files, e.g. see #12226. Is that not necessary anymore?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'll assume it still is, and update accordingly.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes it is still necessary for now. Please add a netcoreapp11 build configuration for these new APIs.

@stephentoub
Copy link
Copy Markdown
Member

Implementation and tests LGTM. Thanks.

return d;
}

public static HashSet<TElement> ToHashSet<TElement>(this IEnumerable<TElement> source) => source.ToHashSet(null);
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.

Should the generic parameter be named TSource to match the naming used by ToList, ToArray, and ToDictionary? TElement is only used for the ToDictionary overloads with an elementSelector.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It was indeed ToDictionary that steered me wrong. Will change to TSource.

@JonHanna JonHanna changed the title Implement Enumerable.ToHashSet() [WIP] Implement Enumerable.ToHashSet() Nov 17, 2016
@JonHanna JonHanna force-pushed the to_hash_set branch 5 times, most recently from eae8abe to c46c1ca Compare November 18, 2016 15:38
@JonHanna
Copy link
Copy Markdown
Contributor Author

I'm missing something silly here. I've got ToHashSetTests.netcoreapp1.1.cs only coming in if '$(TargetGroup)' == 'netcoreapp1.1'. I've got that same condition setting netcoreapp11 and I've got ToHashSet in both ref and src if that directive is set.

What am I missing here?

@mellinoe
Copy link
Copy Markdown
Contributor

Unfortunately it looks like Jenkins deleted all of the logs for that since the links all 404 for me.

@dotnet-bot Test this please

@VSadov
Copy link
Copy Markdown
Member

VSadov commented Nov 19, 2016

implementation and tests LGTM.
I am not up to date with recent requirements in the area of build and versioning.

@JonHanna
Copy link
Copy Markdown
Contributor Author

@mellinoe the error is "'IEnumerable' does not contain a definition for 'ToHashSet'…" and others that suggest that tests\ToHashSetTests.netcoreapp1.1.cs is being compiled against a version of System.Linq that didn't have netcoreapp11 defined when it compiled src\System\Linq\ToCollection.cs

@ericstj
Copy link
Copy Markdown
Member

ericstj commented Nov 21, 2016

@dotnet-bot test Innerloop Windows_NT Debug Build and Test

@ericstj
Copy link
Copy Markdown
Member

ericstj commented Nov 21, 2016

@JonHanna check out the changes here: ericstj@a2274f9

<ItemGroup>
<Project Include="System.Linq.csproj" />
<Project Include="System.Linq.csproj">
<TargetGroup>netcoreapp1.1</TargetGroup>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you please flip and make netcoreapp1.1 the default and the netstandard16 the secondary configuration?

@ericstj
Copy link
Copy Markdown
Member

ericstj commented Nov 21, 2016

When I built locally I also needed to change the name of the generic parameter, otherwise APICompat complained about TElement vs TSource

@JonHanna
Copy link
Copy Markdown
Contributor Author

Ah. I had TElement and then changed to TSource when @justinvp pointed out the latter is more in keeping with when one or the other is used in the rest of the library, but I hadn't fixed the ref version to match. I've made the change there now.

And now it at least builds locally (though that was true of some other problematic pushes) so assuming it builds correctly here I'll sit down and learn what was going on, so I'll actually have some understanding the next time.

Now we play the waiting game…

Thanks.

@JonHanna
Copy link
Copy Markdown
Contributor Author

@ericstj locally my coverage report shows ToHashSet() as being reachable but not covered. Is there something wrong with how I have:

  <ItemGroup Condition="'$(TargetGroup)' == 'netcoreapp1.1'">
    <Compile Include="ToHashSetTests.netcoreapp1.1.cs" />
  </ItemGroup>

As well?

@JonHanna
Copy link
Copy Markdown
Contributor Author

@dotnet-bot test this please.

@JonHanna
Copy link
Copy Markdown
Contributor Author

@dotnet-bot test code coverage

@ericstj
Copy link
Copy Markdown
Member

ericstj commented Nov 21, 2016

@JonHanna can you build src/System.Linq/pkg/System.Linq.pkgproj then address the error?

error : PackageIndex from D:\j\workspace\windows_nt_de---4526f5ff\pkg\Microsoft.Private.PackageBaseline\packageIndex.json is missing an assembly version entry for 4.2.0.0 for package System.Linq.  Please run /t:UpdatePackageIndex on this project to commit an update.

@ericstj
Copy link
Copy Markdown
Member

ericstj commented Nov 21, 2016

WRT to coverage, I think you must be looking at the wrong report. Make sure to look at coverage for the netcoreapp1.1 run of the test.

@JonHanna
Copy link
Copy Markdown
Contributor Author

Thanks that packages step goes some way to explain how things hang together and be less "magic just happens".
I only get one folder of coverage report from MSBuild /t:BuildAndTest /p:Coverage=true. Is there a parameter to pick builds?

@ericstj
Copy link
Copy Markdown
Member

ericstj commented Nov 21, 2016

If you don't specify a project MSBuild picks the one file with a *proj extension, which means it doesn't pass any properties (like TargetGroup). If you want to run it on all configurations, specify the builds file. EG: MSBuild /t:BuildAndTest /p:Coverage=true System.Linq.Tests.builds.

@JonHanna
Copy link
Copy Markdown
Contributor Author

Things are coming up green. Thanks again for your help, @ericstj

@JonHanna JonHanna changed the title [WIP] Implement Enumerable.ToHashSet() Implement Enumerable.ToHashSet() Nov 21, 2016
@JonHanna JonHanna changed the title Implement Enumerable.ToHashSet() [WIP] Implement Enumerable.ToHashSet() Nov 22, 2016
Closes #2323

A straight-forward implementation, forgoing any optimisations.
HashSet's constructor already has some for some cases, and others
could be wasteful unless not just the number of elements, but the
number of elements that are distinct in terms of the equality
comparer can be predicted.
@JonHanna JonHanna changed the title [WIP] Implement Enumerable.ToHashSet() Implement Enumerable.ToHashSet() Nov 23, 2016
@VSadov
Copy link
Copy Markdown
Member

VSadov commented Nov 23, 2016

@weshaggard @ericstj - is this ok to merge now from the build/versioning prospective?

@nawfalhasan
Copy link
Copy Markdown

I dont have a strong opinion on this, just playing devils advocate, should ToHashSet throw on duplicates?

In favour:

  1. ToDictionary throws on duplicates, so ToHashSet too. Just like ToDictionary cant choose which Value to pick, ToHashSet cant pick which reference to choose among the duplicates. Now that we have TryGet on HashSets, worth pondering.

Against:

  1. new HashSet already discards duplicates, so developers expect ToHashSet to do the same.

I know this is shipped, but wondering..

picenka21 pushed a commit to picenka21/runtime that referenced this pull request Feb 18, 2022
Implement Enumerable.ToHashSet()

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

Add Enumerable.ToHashSet