从泛型类继承时需要T的列表或者枚举器的建议
我知道答案将不会很简单,而且我已经使用了一些(我认为很丑陋)的方法。我只是在寻找一些优雅的答案。
抽象类:
public interface IOtherObjects; public abstract class MyObjects<T> where T : IOtherObjects { ... public List<T> ToList() { ... } }
孩子们:
public class MyObjectsA : MyObjects<OtherObjectA> //(where OtherObjectA implements IOtherObjects) { } public class MyObjectsB : MyObjects<OtherObjectB> //(where OtherObjectB implements IOtherObjects) { }
是否有可能遍历MyObjects的集合(或者其他类似的组,泛型或者其他),然后利用MyObjects基类的ToList方法,因为此时我们还不特别了解T的类型。
编辑
对于特定的示例,每当出现这种情况时,我都会考虑一会儿,然后做一些不同的事情,因此没有当前的要求。但是由于它经常出现,所以我想我会把它浮动。
编辑
@Sara,它不是我关心的集合的特定类型,它可以是一个List,但是每个实例的ToList方法仍然相对不可用,没有匿名类型)
@aku,是的,这个问题可能是相对假设的,但是能够知道对象的基本类型将非常有用,但是能够检索并处理T个对象列表。让ToList返回BaseType列表是我的解决方法之一
编辑@全部:到目前为止,这一直是我希望进行的讨论,尽管它在很大程度上证实了我的怀疑。到目前为止,非常感谢,但是还有其他人可以随意输入。
EDIT @ Rob,是的,它适用于已定义的类型,但仅当该类型被称为IOtherObjects列表时无效。
@Rob再次感谢。这通常是我的笨拙变通方法(不要轻视:))。或者使用ConvertAll函数通过委托向下转换。感谢我们抽出宝贵的时间来理解问题。
如果我有点困惑,可以对编辑进行资格审查
更准确地说,(我可能对此的最新实现过于复杂了):
可以说我有两种对象类型,B和C从对象A继承。
许多场景都显示了自己的位置,从B列表或者C列表,或者在其他情况下从B列表或者C列表,但我不知道如果我在基类中,我需要一个不太具体的A列表。
上面的示例是"不太具体问题列表"最新化身的简化示例。
通常,它会自我展示,因为我认为在可能的情况下会限制需要编写的代码量,并且看上去比其他选项要优雅一些。我真的很想讨论关于可能性和其他观点的讨论,我或者多或者少都对此有所了解。令我惊讶的是,到目前为止,还没有人提到ConvertAll(),因为这是我使用的另一种解决方法,但是对于手头的场景来说太冗长了
@罗伯再一次和萨拉
谢谢,但是我确实感到我在所有静态上下文荣耀中都了解泛型,并且确实了解此处的问题。
我们系统的实际设计及其使用的泛型(我可以说这没有一点偏见,因为我只是设计中的一员)。就是在我使用核心API的时候,我发现有些情况下我在做简单事情的时候就处于错误的境地,相反,我不得不以比我所喜欢的稍微优雅一些的方式来处理它们(尝试使自己变得更聪明)也许是懒惰,我会接受其中任何一个标签)。
我不喜欢所谓的"笨拙",主要是因为我们需要遍历记录集,只是将对象转换为其基本值,这可能会降低性能。
我想我想知道以前是否有人在他们的编码中遇到过这种情况,以及是否有人在处理它时比我聪明,或者至少比我更优雅。
解决方案
回答
在情况下,MyObjectsA和MyObjectsB没有共同的前身。通用类是不同类的模板,而不是通用基类。如果要在不同的类中具有公共属性,请使用接口。我们不能在循环中调用ToList,因为它在不同的类中具有不同的签名。我们可以创建返回对象而不是特定类型的ToList。
回答
为什么会有MyObjects的集合?我们没有清单是有特定原因的吗?
回答
我们仍然可能可以访问ToList()方法,但是由于我们不确定类型,因此行不通吗?
foreach(var myObject in myObjectsList) foreach(var obj in myObject.ToList()) //do something
当然,这仅适用于C3.0。
请注意,使用var只是为了消除了解列表包含的类型的要求。与弗兰克(Frank)的评论相反,我有一种幻想,即var将使输入动态化。
回答
泛型用于静态时间类型检查,而不是运行时调度。使用继承/接口进行运行时调度,使用泛型进行编译时类型保证。
interface IMyObjects : IEnumerable<IOtherObjects> {} abstract class MyObjects<T> : IMyObjects where T : IOtherObjects {} IEnumerable<IMyObjects> objs = ...; foreach (IMyObjects mo in objs) { foreach (IOtherObjects oo in mo) { Console.WriteLine(oo); } }
(显然,我更喜欢Enumerables而不是List。)
或者仅使用适当的动态语言,例如VB。 :-)
回答
好的,我很困惑,以下代码对我来说很好(好奇心使我更好!):
// Original Code Snipped for Brevity - See Edit History if Req'd
还是我错过了什么?
根据OP更新响应
好吧,现在我真的很困惑。
我们要说的是要从通用/抽象列表中获取类型值列表吗? (因此,子类无关紧要)。
如果类型是它们不匹配的子代/接口实现者,则不能返回类型列表!我们当然可以从抽象List中获取特定类型的项目的List,如下所示:
public List<OfType> TypedList<OfType>() where OfType : IOtherObjects { List<OfType> rtn = new List<OfType>(); foreach (IOtherObjects o in _objects) { Type objType = o.GetType(); Type reqType = typeof(OfType); if (objType == reqType) rtn.Add((OfType)o); } return rtn; }
如果我仍然不在基地,请我们重新输入问题吗?! (似乎我并不是唯一一个不确定我们开车到哪里去的人)。我正在尝试确定我们是否对仿制药有误解。
另一个更新:D
是的,所以看起来我们想要/需要获取类型化列表的选项,还是基本列表是?
这将使抽象类看起来像这样,我们可以使用ToList获取具体类型,或者使用ToBaseList()获取接口类型的List。这应该在我们遇到的任何情况下都有效。有帮助吗?
public abstract class MyObjects<T> where T : IOtherObjects { List<T> _objects = new List<T>(); public List<T> ToList() { return _objects; } public List<IOtherObjects> ToBaseList() { List<IOtherObjects> rtn = new List<IOtherObjects>(); foreach (IOtherObjects o in _objects) { rtn.Add(o); } return rtn; } }
更新#3
这不是真正的"笨拙"的解决方法(不要轻视),这是唯一的解决方法。我认为这里更大的问题是设计/问题。我们说我们有问题,此代码可以解决。但是,如果我们期望执行以下操作:
public abstract class MyObjects<T> where T : IOtherObjects { List<T> _objects = new List<T>(); public List<IOtherObjects> Objects { get { return _objects; } } } #warning This won't compile, its for demo's sake.
并能够选择其中的类型,我们还能怎么做?我感觉到我们不太了解泛型的意义,而我们正试图让它们做一些他们不适合做的事情!
回答
如果你有
class B : A class C : A
你有
List<B> listB; List<C> listC;
我们希望将其视为父类型的列表
那你应该用
List<A> listA = listB.Cast<A>().Concat(listC.Cast<A>()).ToList()
回答
我最近发现了
List<A>.Cast<B>().ToList<B>()
图案。
正是我想要的,