从列表中获取可能包含其他类型的泛型类型的所有项目的列表 [英] Get list of all items of a generic type from list which could contain other types
问题描述
清单< Foo>我的列表;
Foo
是一个常见的抽象类,它是用于系统中的所有组件。其中一些组件类是通用的:
public class Bar< T> :Foo
{
public void MethodCommonToAllBar()
{
...
}
}
有些类可能会扩展通用类:
public class Baz:Bar< int>
public class Bat:Bar< string>
我想从 MyList
一组所有类型为 Bar< anything>
的对象,以便我可以在每个对象上调用 MethodCommonToAllBar()
那些东西。如果不是泛型,我可以使用如下行:
foreach(Baz baz in MyList.Where( x => x是Baz))
{
baz.MethodCommonToAllBar();
}
foreach(Bat bat in MyList.Where(x => x is Bat))
{
bat.MethodCommonToAllBar();
}
甚至是
<$在MyList.Where中的Bar< int> bar(x => x是Bar< int>))
{
bar.MethodCommonToAllBar();
}
foreach(MyList.Where中的Bar< string> bar(x => x是Bar< string>))
{
bar.MethodCommonToAllBar();
}
但似乎没有办法让任何对象类型 Bar
,除非我分开处理每个潜在的子类型。有没有解决方法?假设我不能以任何方式改变类结构。 (我可以,但是这是一个很大的项目,这样的改变会影响很多人,所以不太可能得到批准。理想情况下,我会在 Foo之间添加另一个非泛型类
和 Bar< T>
来存储该方法和其他任何常见的东西,然后搜索它。这个游戏现在正在进行重构)。我还可以看到一个涉及Reflection的解决方法,但这看起来像是矫枉过正,并且可能会导致性能下降。有没有其他方法可以干净地处理这个问题?解决方案
$ c> Bar< X> 和
Bar< Y>
不兼容!它们只是源自共同祖先的两种不同类型。它们都是同一个开放泛型类型的具体实现的事实没有区别。 您想如何处理它们?假设您从列表中检索到
Bar <?>>
类型的未知泛型类型的对象,并且您有一个方法 void ProcessBar< T>(){...}
你从哪里知道 T
的正确值?请注意, T
在编译时解析,而不是在运行时!这就是泛型的用途:通过保持类型安全来提供一定的灵活性。只有在编译时才能实现类型安全。
解决此问题的一种方法实际上是在继承层次结构中引入非泛型中间类型。如果你不能改变继承层次,让所有 Bar< T>
实现一个非泛型接口 IBar
public interface IBar
{
void MethodCommonToAllBar();
}
并简单地使用
foreach(IBar bar in MyList.OfType< IBar>())
{
bar.MethodCommonToAllBar(); // IBar中定义的方法。
请注意 另一种方法是不使用泛型,并使用 类型安全性和动态灵活性是对手。 Okay, this is tricky. Say I have a list: And some classes may extend the generic ones: I'd like a way to extract from or even But there doesn't seem to be any way to get all objects of any type of You must you be aware of the fact that the two types Where do you know the right value of One way of solving this problem is in fact to introduce a non-generic intermediate type in your inheritance hierarchy. If you cannot change the inheritance hierachy, let all and simply filter your list with Note that Another way is to not use generics at all and to work with the Type safety and dynamic flexibility are opponents. 这篇关于从列表中获取可能包含其他类型的泛型类型的所有项目的列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! OfType<> $ c
对象键入
Bar
类以获得最大的动态灵活性。
List<Foo> MyList;
Foo
is a common abstract class which is used for all components in the system. Some of these component classes are generic:public class Bar<T> : Foo
{
public void MethodCommonToAllBar()
{
...
}
}
public class Baz : Bar<int>
public class Bat : Bar<string>
MyList
a set of all objects of type Bar<anything>
, so that I may call MethodCommonToAllBar()
on each of those things. If it weren't for the generic here, I could use a line like:foreach (Baz baz in MyList.Where(x => x is Baz))
{
baz.MethodCommonToAllBar();
}
foreach (Bat bat in MyList.Where(x => x is Bat))
{
bat.MethodCommonToAllBar();
}
foreach (Bar<int> bar in MyList.Where(x => x is Bar<int>))
{
bar.MethodCommonToAllBar();
}
foreach (Bar<string> bar in MyList.Where(x => x is Bar<string>))
{
bar.MethodCommonToAllBar();
}
Bar
unless I treat each potential subtype separately. Is there a workaround for this? Assume that I can't change the class structure in any way. (I could, but it's a big project, and such a change would impact a lot of people, so it's unlikely I'd get it approved. Ideally, I'd add another non-generic class between Foo
and Bar<T>
in the hierarchy to store that method and any other such common things and just search for that. But it's a bit late in the game to go refactoring that now.) I can also see a workaround involving Reflection, but that seems like overkill, and would likely incur a performance hit to boot. Is there any other way to handle this cleanly?Bar<X>
and Bar<Y>
are not compatible! They are just two different types deriving from a common ancestor. The fact that they are both concrete implementations of the same open generic type makes no difference.
And how do you want to process them? Assume that you retrieved an object of type Bar<?>
of an unknown generic type from the list and that you have a methodvoid ProcessBar<T>() { ... }
T
from? Note that T
is resolved at compile time, not at runtime! This is what generics are for: to provide certain flexibility by keeping type safety. And type safety can only be achieved at compile time.Bar<T>
implement a non-generic interface IBar
public interface IBar
{
void MethodCommonToAllBar();
}
foreach (IBar bar in MyList.OfType<IBar>())
{
bar.MethodCommonToAllBar(); // Method defined in IBar.
}
OfType<>
does both, filter and cast to the required type.object
type in the Bar
class for maximum dynamic flexibility.