Reputation: 103
I have a extension taking the value of an enum as a parameter, and return a collection of its Select
result.
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;
}
}
And Alignment
, Faction
are each by themselves enums.
Such as
public enum AlignmentType {ChaoticEvil, LawfulGood, etc.}
public enum FactionType {Human, Undead, etc.}
So the return types will be, respectively, List<AlignmentType>
, List<FactionType>
, List<int>
.
So the final return type inevitably have to be object
.
But I soon find out that I can't cast it back into its original type (eg. List<FactionType>
) because "I don't know what type it is"!
I can't use generic type neither because the result is depended on the "value" of its parameter.
And I can't use polymorphism because of the same reason.
So somebody please be so kind and tell me what solutions do I have?
Much appreciated!
Upvotes: 0
Views: 90
Reputation: 2317
You seem to want a flexible way to select/map instances of base
to child properties of various type. Is this correct? If so how about:
public static List<T> Map<T>(this List<Base> bases, Func<Base, T> mapper) => bases.Select(mapper).ToList();
usage:
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);
If not, then @litelite suggestions of having return types all implement a common interface is the approach I would also take.
Upvotes: 1
Reputation: 2851
I feel your problem goes down to the architecture of your code. The "clean" way would have been to have a common interface which all your different return types would implement and return a list of that. If you dont have a common type you will always be stuck with this problem. Otherwise you could split it in 3 methods or return an object wich contains the return value and a flag which indicates de type of the value but that last option should be a last resort.
For your specific case I think the best way would be to split that method in three like this :
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();
}
Upvotes: 3
Reputation: 5804
So the final return type inevitably have to be object. Looks like you return a list or null, so the return type could be
IEnumerable?
https://learn.microsoft.com/en-us/dotnet/api/system.collections.ienumerable?view=net-5.0
But I soon find out that I can't cast it back into its original type (eg. List) because "I don't know what type it is"!
If there can be multiple types, you'll have to test, which type you have, e.g.
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
Upvotes: 1