从 LINQ 查询返回命名元组
Returning a named tuple from a LINQ query
我整天都在尝试,尝试了很多次,但运气不好。我有以下 returns 结果的 Linq 查询。
此查询 returns IEnumerable:
var temp = from entity in remainingEntities
where entity.EndPoint.FuzzyEqual(matchPoint, _tolerance)
select entity;
此查询returns(IEnumerable,结束)
var temp = (from entity in remainingEntities
where entity.EndPoint.FuzzyEqual(matchPoint, _tolerance)
select entity, ChainMatchType.End);
这两个都不是我想要的。最终 IEnumerable 中的每个结果都需要是一个命名元组,每个元组都有一个 ISketchEntity 和 ChainMatchType:
List<(ISketchEntity sketchEntityName, ChainMatchType MatchName)>
我将在三个不同的时间进行类似的查询。
- 当某些类型的 ISketchEntities 匹配端点时。
- 当某些类型的 ISketchEntities 匹配起点时。
- 当某些类型的 ISketchEntities 与 CenterPoint 匹配时。
当我 运行 每个查询时,我想添加结果类型,使用枚举来表示匹配类型。
public enum ChainMatchType
{
Start,
End,
Center
}
我的计划是在返回结果之前将所有三个查询合并为一个结果。
如何格式化我的 LINQ 以将结果放入命名元组中:
Name DataType
entity: ISketchEntity
MatchType: ChainMatchType
编辑
FuzzyEquals 是一个自定义扩展。它使用 +/- 公差比较两点。我正在处理 CAD 数据,过去的历史告诉我,有时两点可能足够接近以至于相等,但坐标并不完全相同。
public static bool FuzzyEqual(this ISketchPoint sp, ISketchPoint other, double tolerance)
{
if (
sp.X > other.X - tolerance && sp.X < other.X + tolerance &&
sp.Y > other.Y - tolerance && sp.Y < other.Y + tolerance &&
sp.Z > other.Z - tolerance && sp.Z < other.Z + tolerance
)
return true;
return false;
}
刚才看了觉得可以简化为:
public static bool FuzzyEqual(this ISketchPoint sp, ISketchPoint other, double tolerance)
{
return sp.X > other.X - tolerance && sp.X < other.X + tolerance &&
sp.Y > other.Y - tolerance && sp.Y < other.Y + tolerance &&
sp.Z > other.Z - tolerance && sp.Z < other.Z + tolerance;
}
您只需要在 select 部分使用大括号:
var temp = (from entity in remainingEntities
where entity.EndPoint.FuzzyEqual(matchPoint, _tolerance)
select (entity, ChainMatchType.End));
- 我建议使用仅具有扩展方法的 Linq,并避免关键字样式
from
、in
、where
、select
。
- 我承认这是我的个人偏好 - 但 C# 的 Linq 关键字功能有点乏味,你几乎总是结束-up 需要使用一些扩展方法(尤其是
ToList
和 Include
)并且混合使用关键字和扩展方法样式会使事情更难阅读。
- 无论如何,您只需要在
Select
步骤中添加值元组,它可以是方法参数(尽管您不能 easily 参数化值元组成员名称 - 这是可能的,但超出了这个问题的范围)。
像这样:
List<( ISketchEntity sketchEntityName, ChainMatchType matchName )> withName = remainingEntities
.Where( e => e.EndPoint.FuzzyEqual( matchPoint, _tolerance ) )
.Select( e => ( sketchEntityName: e, matchName: matchName ) )
.ToList()
作为参数化方法:
(顺便说一句,我不知道 matchPoint
和 _tolerance
是什么)。
public static List<( ISketchEntity sketchEntityName, ChainMatchType matchName )> Get2( this IEnumerable<ISketchEntity> entities, ChainMatchType matchType )
{
// Precondition:
if( entities is null ) throw new ArgumentNullException(nameof(entities));
return entities
.Where( e => e.EndPoint.FuzzyEqual( matchPoint, _tolerance ) )
.Select( e => ( sketchEntityName: e, matchName: matchType ) )
.ToList()
}
我整天都在尝试,尝试了很多次,但运气不好。我有以下 returns 结果的 Linq 查询。
此查询 returns IEnumerable
var temp = from entity in remainingEntities
where entity.EndPoint.FuzzyEqual(matchPoint, _tolerance)
select entity;
此查询returns(IEnumerable
var temp = (from entity in remainingEntities
where entity.EndPoint.FuzzyEqual(matchPoint, _tolerance)
select entity, ChainMatchType.End);
这两个都不是我想要的。最终 IEnumerable 中的每个结果都需要是一个命名元组,每个元组都有一个 ISketchEntity 和 ChainMatchType:
List<(ISketchEntity sketchEntityName, ChainMatchType MatchName)>
我将在三个不同的时间进行类似的查询。
- 当某些类型的 ISketchEntities 匹配端点时。
- 当某些类型的 ISketchEntities 匹配起点时。
- 当某些类型的 ISketchEntities 与 CenterPoint 匹配时。
当我 运行 每个查询时,我想添加结果类型,使用枚举来表示匹配类型。
public enum ChainMatchType
{
Start,
End,
Center
}
我的计划是在返回结果之前将所有三个查询合并为一个结果。
如何格式化我的 LINQ 以将结果放入命名元组中:
Name DataType
entity: ISketchEntity
MatchType: ChainMatchType
编辑 FuzzyEquals 是一个自定义扩展。它使用 +/- 公差比较两点。我正在处理 CAD 数据,过去的历史告诉我,有时两点可能足够接近以至于相等,但坐标并不完全相同。
public static bool FuzzyEqual(this ISketchPoint sp, ISketchPoint other, double tolerance)
{
if (
sp.X > other.X - tolerance && sp.X < other.X + tolerance &&
sp.Y > other.Y - tolerance && sp.Y < other.Y + tolerance &&
sp.Z > other.Z - tolerance && sp.Z < other.Z + tolerance
)
return true;
return false;
}
刚才看了觉得可以简化为:
public static bool FuzzyEqual(this ISketchPoint sp, ISketchPoint other, double tolerance)
{
return sp.X > other.X - tolerance && sp.X < other.X + tolerance &&
sp.Y > other.Y - tolerance && sp.Y < other.Y + tolerance &&
sp.Z > other.Z - tolerance && sp.Z < other.Z + tolerance;
}
您只需要在 select 部分使用大括号:
var temp = (from entity in remainingEntities
where entity.EndPoint.FuzzyEqual(matchPoint, _tolerance)
select (entity, ChainMatchType.End));
- 我建议使用仅具有扩展方法的 Linq,并避免关键字样式
from
、in
、where
、select
。- 我承认这是我的个人偏好 - 但 C# 的 Linq 关键字功能有点乏味,你几乎总是结束-up 需要使用一些扩展方法(尤其是
ToList
和Include
)并且混合使用关键字和扩展方法样式会使事情更难阅读。
- 我承认这是我的个人偏好 - 但 C# 的 Linq 关键字功能有点乏味,你几乎总是结束-up 需要使用一些扩展方法(尤其是
- 无论如何,您只需要在
Select
步骤中添加值元组,它可以是方法参数(尽管您不能 easily 参数化值元组成员名称 - 这是可能的,但超出了这个问题的范围)。
像这样:
List<( ISketchEntity sketchEntityName, ChainMatchType matchName )> withName = remainingEntities
.Where( e => e.EndPoint.FuzzyEqual( matchPoint, _tolerance ) )
.Select( e => ( sketchEntityName: e, matchName: matchName ) )
.ToList()
作为参数化方法:
(顺便说一句,我不知道 matchPoint
和 _tolerance
是什么)。
public static List<( ISketchEntity sketchEntityName, ChainMatchType matchName )> Get2( this IEnumerable<ISketchEntity> entities, ChainMatchType matchType )
{
// Precondition:
if( entities is null ) throw new ArgumentNullException(nameof(entities));
return entities
.Where( e => e.EndPoint.FuzzyEqual( matchPoint, _tolerance ) )
.Select( e => ( sketchEntityName: e, matchName: matchType ) )
.ToList()
}