我有一个作为ISet的类的属性。我正在尝试将linq查询的结果放入该属性中,但无法弄清楚该怎么做。
基本上,寻找这的最后一部分:
ISet<T> foo = new HashedSet<T>();
foo = (from x in bar.Items select x).SOMETHING;
也可以这样做:
HashSet<T> foo = new HashSet<T>();
foo = (from x in bar.Items select x).SOMETHING;
我有一个作为ISet的类的属性。我正在尝试将linq查询的结果放入该属性中,但无法弄清楚该怎么做。
基本上,寻找这的最后一部分:
ISet<T> foo = new HashedSet<T>();
foo = (from x in bar.Items select x).SOMETHING;
也可以这样做:
HashSet<T> foo = new HashSet<T>();
foo = (from x in bar.Items select x).SOMETHING;
Answers:
我不认为有什么内置函数可以执行此操作……但是编写扩展方法确实很容易:
public static class Extensions
{
public static HashSet<T> ToHashSet<T>(
this IEnumerable<T> source,
IEqualityComparer<T> comparer = null)
{
return new HashSet<T>(source, comparer);
}
}
请注意,您实际上确实希望在这里使用扩展方法(或至少某种形式的通用方法),因为您可能无法明确表示类型T
:
var query = from i in Enumerable.Range(0, 10)
select new { i, j = i + 1 };
var resultSet = query.ToHashSet();
您不能通过显式调用 HashSet<T>
构造函数。我们依靠泛型方法的类型推断来为我们做到这一点。
现在您可以选择命名ToSet
并返回ISet<T>
-但我会坚持使用ToHashSet
具体类型。这与标准LINQ运算符()一致ToDictionary
,ToList
并允许将来进行扩展(例如ToSortedSet
)。您可能还需要提供一个重载,以指定要使用的比较。
GetHashCode
和Equals
?如果不是这样的话,他们在HashSet中的表现将不会很好...
ForEach
,但ToHashSet
更有意义-我不知道ToHashSet
除了正常的“不符合实用性标准”(我不同意,但是...)
只需将IEnumerable传递给HashSet的构造函数即可。
HashSet<T> foo = new HashSet<T>(from x in bar.Items select x);
bar.Items
都会是T
。考虑到实现此通用目的的难度,以及LINQ中出现匿名类型的频率,我认为值得采取额外的措施。
有在.NET框架和.NET核心扩展方法构建用于转换IEnumerable
到一个HashSet
:https://docs.microsoft.com/en-us/dotnet/api/?term=ToHashSet
public static System.Collections.Generic.HashSet<TSource> ToHashSet<TSource> (this System.Collections.Generic.IEnumerable<TSource> source);
看来(在撰写本文时)我还不能在.NET标准库中使用它。因此,我使用了这种扩展方法:
[Obsolete("In the .NET framework and in NET core this method is available, " +
"however can't use it in .NET standard yet. When it's added, please remove this method")]
public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source, IEqualityComparer<T> comparer = null) => new HashSet<T>(source, comparer);
那很简单:)
var foo = new HashSet<T>(from x in bar.Items select x);
是的T是OP指定的类型:)
乔恩的答案很完美。唯一需要注意的是,使用NHibernate的HashedSet,我需要将结果转换为集合。有没有最佳的方法来做到这一点?
ISet<string> bla = new HashedSet<string>((from b in strings select b).ToArray());
要么
ISet<string> bla = new HashedSet<string>((from b in strings select b).ToList());
还是我想念其他东西?
编辑:这就是我最终要做的事情:
public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source)
{
return new HashSet<T>(source);
}
public static HashedSet<T> ToHashedSet<T>(this IEnumerable<T> source)
{
return new HashedSet<T>(source.ToHashSet());
}
ToList
通常比ToArray
。是否只需要执行ICollection<T>
?
与其简单地将IEnumerable转换为HashSet,不如将另一个对象的属性转换为HashSet通常很方便。您可以这样写:
var set = myObject.Select(o => o.Name).ToHashSet();
但是,我更喜欢使用选择器:
var set = myObject.ToHashSet(o => o.Name);
他们做同样的事情,第二个明显短一些,但是我发现这个成语更适合我的大脑(我认为它就像ToDictionary)。
这是要使用的扩展方法,另外还支持自定义比较器。
public static HashSet<TKey> ToHashSet<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> selector,
IEqualityComparer<TKey> comparer = null)
{
return new HashSet<TKey>(source.Select(selector), comparer);
}
HashedSet
省略-part。因为这很混乱,C#
而且LINQ
没有任何名称HashedSet
。