我知道答案并不简单,我已经使用了一些(我觉得很丑陋)的cludges。我只是在寻找一些优雅的答案。
抽象类:
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,true,这个问题可能是相对假设的,但是能够检索并使用T对象列表,只知道它们的基类型将非常有用。让ToList返回List of BaseType是我的解决方法之一
编辑 @ all:到目前为止,这是我希望的那种讨论,尽管它在很大程度上证实了我所怀疑的一切。谢谢所有人,但其他任何人都可以随意输入。
编辑 @Rob,是的,它适用于已定义的类型,但不适用于仅将类型称为IOtherObjects列表的情况。
@Rob 再次谢谢。这通常是我的狡猾的解决方法(没有不尊重:))。或者使用ConvertAll函数通过委托进行Downcast。感谢您花时间了解问题。
合格编辑,以防我有点困惑
更确切地说,(我可能已经让我最近的实现变得太复杂了):
假设我有2个对象类型,B和C继承自对象A.
很多场景都出现在B列表或C列表中,或者在其他情况下列出了一个列表 - 但我不知道如果我在基类,我需要少一些具体的A.清单。
上面的例子是 List Of Less Specific 问题的最新版本的一个淡化例子。
通常它已经出现了,因为我认为可能的场景限制了需要编写的代码量,并且看起来比其他选项更优雅。我真的想要讨论可能性和其他观点,我或多或少都有。我很惊讶到目前为止还没有人提到ConvertAll(),因为这是我使用过的另一种解决方法,但对于手头的场景来说有点过于冗长
@Rob 又一次和Sara
谢谢,但是我确实觉得我理解他们所有静态背景中的泛型,并且确实理解了这里的问题。
我们系统的实际设计和仿制药的使用(我可以说这不仅仅是一点偏见,因为我只是设计中的一员),已经做得很好。就在我使用核心API的时候,我已经找到了一些情况,当我在一个错误的范围内做一些简单的事情,而不是我不得不处理它们而不是我喜欢的那么优雅(试图要聪明或者懒惰 - 我会接受其中任何一个标签。)
我对我称之为“污垢”的厌恶主要是我们需要在记录集中循环,只是将对象转换为可能会影响性能的基值。
我想我想知道是否有其他人在他们的编码之前遇到过这种情况,如果有人在处理它时比我更聪明,或者至少更优雅。
答案 0 :(得分:2)
在你的情况下,MyObjectsA和MyObjectsB没有共同的前任。泛型类是不同类的模板,而不是公共基类。如果要在不同的类中使用公共属性,请使用接口。您不能在循环中调用 ToList ,因为它在不同的类中具有不同的签名。您可以创建返回对象而不是特定类型的ToList。
答案 1 :(得分:2)
为什么你有一个MyObjects的集合?您是否有特定原因没有列表?
答案 2 :(得分:1)
您仍然可以访问ToList()方法,但由于您不确定该类型,这不会起作用吗?
foreach(var myObject in myObjectsList)
foreach(var obj in myObject.ToList())
//do something
当然这只适用于C#3.0。
请注意,var的使用仅仅是为了消除知道列表包含什么类型的要求;与弗兰克的评论相反,我认为var会使打字变得动态。
答案 3 :(得分:1)
好的,我很困惑,以下代码对我来说很好(好奇心让我变得更好!):
// Original Code Snipped for Brevity - See Edit History if Req'd
或者我错过了什么?
如果类型是子/接口实现者,则无法返回类型列表 - 它们不匹配!您当然可以从抽象列表中获取特定类型的项目列表,如下所示:
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;
}
如果我仍然离开这里,你可以改回你的问题吗?! (似乎我不是唯一一个不确定你驾驶的人)。我试图确定你是否存在对泛型的误解。
是的,所以看起来你想要/需要选项来获取类型化列表,或基本列表是吗?
这将使您的抽象类看起来像这样 - 您可以使用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;
}
}
这不是一个“cludgy”的解决方法(没有不尊重) - 这是唯一的方法。我认为这里更大的问题是设计/问题。你说你遇到了问题,这段代码解决了这个问题。但是,如果你期望做类似的事情:
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.
并且能够挑选出来的类型,可以你怎么做?!我觉得你并不真正理解泛型的含义是什么,而你正试图让他们做一些他们不是为了设计的东西!?
答案 4 :(得分:1)
如果你有
class B : A
class C : A
你有
List<B> listB;
List<C> listC;
您希望将其视为父类型的列表
然后你应该使用
List<A> listA = listB.Cast<A>().Concat(listC.Cast<A>()).ToList()
答案 5 :(得分:0)
我最近找到了
List<A>.Cast<B>().ToList<B>()
图案。
它完全符合我的要求,
答案 6 :(得分:-1)
泛型用于静态时间类型检查不运行时调度。使用inheritance / interfaces进行运行时调度,使用泛型进行编译时类型保证。
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而不是列表。)
OR 只需使用适当的动态语言,如VB。 : - )