我在一个类上有一个属性,它是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;
当前回答
乔恩的回答很完美。唯一需要注意的是,使用NHibernate的HashedSet,我需要将结果转换为一个集合。有没有最佳的方法来做到这一点?
ISet<string> bla = new HashedSet<string>((from b in strings select b).ToArray());
or
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());
}
其他回答
我不认为有任何东西可以做到这一点。但是写一个扩展方法真的很容易:
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)。您可能还希望提供一个重载,指定要使用的比较。
在.NET框架和.NET核心中有一个用于将IEnumerable转换为HashSet的扩展方法:https://learn.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());
or
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());
}
与其简单地将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);
}