我有一个扩展,将枚举的值作为参数,并返回其Select
结果的集合。
public static object Filter(this List<Base> bases, FilterType type)
{
switch(type)
{
case FilterType.Alignment:
return bases.Select(x => x.Alignment).ToList();
case FilterType.Faction:
return bases.Select(x => x.Faction).ToList();
case FilterType.HP:
return bases.Select(x => x.HP).ToList();
...
default:
return null;
}
}
并且Alignment
、Faction
各自是枚举。
如
public enum AlignmentType {ChaoticEvil, LawfulGood, etc.}
public enum FactionType {Human, Undead, etc.}
因此,返回类型将分别为List<AlignmentType>
、List<FactionType>
和List<int>
。
因此,最终返回类型不可避免地必须是object
。
但我很快发现,我无法将其投射回其原始类型(例如List<FactionType>
(,因为";我不知道它是什么类型的"!
我也不能使用泛型类型,因为结果取决于";值";的参数。
由于同样的原因,我不能使用多态性。
所以有人请好心告诉我我有什么解决方案?
非常感谢!
我觉得您的问题归根结底在于代码的体系结构。";"干净";方法是拥有一个通用接口,所有不同的返回类型都将实现该接口并返回该接口的列表。如果你没有一个共同的类型,你将永远陷入这个问题。否则,您可以将其拆分为3个方法,或者返回一个对象,该对象包含返回值和一个指示值取消类型的标志,但最后一个选项应该是最后的选择。
对于您的具体情况,我认为最好的方法是将该方法分为三种,如下所示:
public static List<AlignmentType> FilterAlignment(this List<Base> bases)
{
return bases.Select(x => x.Alignment).ToList();
}
public static List<FactionType> FilterFaction(this List<Base> bases)
{
return bases.Select(x => x.Faction).ToList();
}
public static List<int> FilterHP(this List<Base> bases)
{
return bases.Select(x => x.HP).ToList();
}
因此,最终返回类型不可避免地必须是对象。看起来您返回了一个列表或null,因此返回类型可能是
IEnumerable?
https://learn.microsoft.com/en-us/dotnet/api/system.collections.ienumerable?view=net-5.0
但我很快发现我无法将其转换回原来的类型(例如List(,因为"我不知道它是什么类型的"!
如果可以有多种类型,您必须测试您拥有的类型,例如
var filtered = mylist.Filter(FilterType.Alignment);
var processed = filtered switch {
List<AlignmentType> lat => // do something
_ => throw new Exception("not supported")
};
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/switch-expression
您似乎想要一种灵活的方法来选择/映射base
的实例到各种类型的子属性。这是正确的吗?如果是的话:
public static List<T> Map<T>(this List<Base> bases, Func<Base, T> mapper) => bases.Select(mapper).ToList();
用法:
List<Base> bases = ...
List<FactionType> mappedFactions = bases.Map(b => b.Faction);
List<AlignmentType> mappedAligntments = bases.Map(b => b.Alignment);
List<int> mappedHPs = bases.Map(b => b.HP);
如果没有,那么@litelite建议让返回类型都实现一个公共接口也是我会采取的方法。