查询字典中列表的元素以获取通用类型

huangapple go评论79阅读模式
英文:

Query elements of a list inside a dictionary for generic type

问题

private readonly Dictionary<IntBound, List> structuresDataCollection;

我们可以像这样获取RoadStructureData(它继承自StructureData):

public IEnumerable<RoadStructureData> GetRoadDataWithin(IntBound position)
{
    return structuresDataCollection.Where(s => s.Key.Intersects(position)).Where(s => s.Value.OfType<RoadStructureData>().Any()).Select(s => s.Value);
}

但我需要编写一个更通用的方法,以获取所选IntBound的指定子类型的StructureData

我想它可以看起来像这样:

public IEnumerable<StructureData> GetDataWithinOfType(IntBound position, Type requiredType)
{
    return structuresDataCollection.Where(s => s.Key.Intersects(position)).Where(s => s.Value.Any(v => requiredType.IsAssignableFrom(v.GetType()))).Select(s => s.Value);
}

但是我们不能在OfType<Type>()方法中使用Type变量。如何重写这段代码?

英文:

I have a dictionary with a key and values as a list with my class StructureData.

private readonly Dictionary&lt;IntBound, List&lt;StructureData&gt;&gt; structuresDataCollection;

We can get RoadStructureData (which inherits StructureData) like this:

public IEnumerable&lt;RoadStructureData&gt; GetRoadDataWithin(IntBound position)
{
    return (IEnumerable&lt;RoadStructureData&gt;)structuresDataCollection.Where(s =&gt; s.Key.Intersects(position)).Where(s =&gt; s.Value.OfType&lt;RoadStructureData&gt;().Any()).Select(s =&gt; s.Value);
}

But I need to write a more generic method to get StructureData for a specified child type for a selected IntBound.

I suppose it could look like this:

public IEnumerable&lt;StructureData&gt; GetDataWithinOfType(IntBound position, Type requiredType)
{
    return structuresDataCollection.Where(s =&gt; s.Key.Intersects(position)).Where(s =&gt; s.Value.OfType&lt;requiredType&gt;().Any()).Select(s =&gt; s.Value);
}

But we can't use a Type variable in the OfType&lt;Type&gt;() method. How to rewrite this code?

答案1

得分: 0

使用泛型:

public IEnumerable<T> GetRoadDataWithin<T>(IntBound position)
    where T : StructureData
    => structuresDataCollection
        .Where(s => s.Key.Intersects(position))
        .Where(s => s.Value.OfType<T>().Any())
        .Select(s => s.Value.OfType<T>());

OfType<T> 将返回一个 IEnumerable<T>,因此您不需要额外的强制转换(即 OfType<RoadStructureData> 将返回一个 IEnumerable<RoadStructureData>

用法:

var roadStructureData = GetRoadDataWithin<RoadStructureData>(position);

顺便说一下,注意此代码(与您编写的代码一样)假定每个列表只能具有一种特定类型 - 例如,如果有两种继承 StructureData 的类型 XY,每个列表只能包含 X 或只能包含 Y,不能有一个列表既包含 X 又包含 Y

英文:

Use generics:

public IEnumerable&lt;T&gt; GetRoadDataWithin&lt;T&gt;(IntBound position)
    where T : StructureData
    =&gt; structuresDataCollection
        .Where(s =&gt; s.Key.Intersects(position))
        .Where(s =&gt; s.Value.OfType&lt;T&gt;().Any())
        .Select(s =&gt; s.Value.OfType&lt;T&gt;());

The OfType&lt;T&gt; will return an IEnumerable&lt;T&gt;, so you don't need the extra cast (i.e OfType&lt;RoadStructureData&gt; will return an IEnumerable&lt;RoadStructureData&gt;)

usage:

var roadStructureData = GetRoadDataWithin&lt;RoadStructureData&gt;(position);

BTW, note that this code (like the code you wrote) assumes that each list can only have one specific type - so if for instance you have both X and Y types inheriting StructureData, each list can hold only X or only Y, you can't have a list where some items will be X and others Y.

huangapple
  • 本文由 发表于 2023年8月10日 17:00:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/76874171.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定