我知道答案并不简单,而且我已经使用了一些(我认为丑陋的)木棍。我只是在寻找一些优雅的答案。

抽象类:

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 的集合(或其他类似的分组,通用或其他),然后利用 待列表 的方法 我的对象 基类,因为我们此时并不具体知道 T 的类型。

编辑至于具体的例子,每当出现这个问题时,我都会想一想,然后做一些不同的事情,所以目前没有要求。但由于它经常出现,我想我应该把它浮动。

编辑@Sara,这不是我关心的集合的具体类型,它可能是一个 List,但每个实例的 ToList 方法仍然相对不可用,没有匿名类型)

@aku,是的,这个问题可能是相对假设的,但是能够检索并使用 T 个对象的列表,只知道它们的基本类型将非常有用。让 ToList 返回 BaseType 列表是我的解决方法之一

编辑 @ 全部:到目前为止,这一直是我所希望的讨论,尽管它在很大程度上证实了我的所有怀疑。到目前为止,谢谢大家,但其他人请随意输入。

编辑@Rob,是的,它适用于定义的类型,但当该类型仅被称为 IotherObjects 列表时则不起作用。

@抢 再次 谢谢。这通常是我笨拙的解决方法(没有不尊重的意思:))。或者使用 ConvertAll 函数通过委托向下转换。感谢您花时间了解问题。

合格编辑 以防我有点困惑

更准确地说,(我可能让我最新的实现变得过于复杂):

假设我有 2 个对象类型,B 和 C 继承自对象 A。

许多场景已经呈现在其中,从 B 列表或 C 列表,或者在其他情况下是其中任何一个列表 - 但我不知道如果我在基类中,我需要一个不太具体的列表A。

上面的例子是一个淡化的例子 不太具体的清单 问题的最新体现。

通常它已经出现了,因为我认为通过可能的场景限制了需要编写的代码量,并且看起来比其他选项更优雅一些。我真的很想讨论可能性和其他观点,我或多或少已经得到了这些。我很惊讶到目前为止没有人提到 ConvertAll(),因为这是我使用过的另一种解决方法,但对于当前的场景来说有点过于冗长

@抢 再次 和萨拉

谢谢,但是我确实觉得我理解泛型的所有静态上下文荣耀,并且确实理解这里起作用的问题。

我们系统的实际设计和泛型的使用(我可以毫无偏见地这么说,因为我只是设计中的参与者之一),已经做得很好了。当我使用核心 API 时,我发现了一些情况,当我简单地做一些事情时,我处于错误的范围内,相反,我不得不用比我喜欢的稍微不那么优雅的方式来处理它们(尝试要么聪明一点)或者也许是懒惰 - 我会接受这些标签中的任何一个)。

我对我所说的“cludge”的厌恶很大程度上是因为我们需要对记录集进行循环,只是为了将对象转换为其基本值,这可能会影响性能。

我想我想知道是否有其他人以前在编码中遇到过这个问题,以及是否有人在处理它时比我更聪明,或者至少更优雅。

有帮助吗?

解决方案

如果你有

class B : A
class C : A

你有

List<B> listB;
List<C> listC;

您希望将其视为父类型的列表

那么你应该使用

List<A> listA = listB.Cast<A>().Concat(listC.Cast<A>()).ToList()

其他提示

为什么你有一个 MyObjects 集合?您没有列表有什么具体原因吗?

在您的情况下,MyObjectsA 和 MyObjectsB 没有共同的前身。通用类是模板 不同的 类不是公共基类。如果你想在不同的类中拥有共同的属性,请使用接口。你不能打电话 待列表 在循环中,因为它在不同的类中有不同的签名。您可以创建返回的 ToList 物体 而不是具体类型。

您仍然可以访问 ToList() 方法,但由于您不确定类型,这不起作用吗?

foreach(var myObject in myObjectsList)
    foreach(var obj in myObject.ToList())
        //do something

当然这仅适用于 C# 3.0。

请注意,使用 var 只是为了消除了解列表包含什么类型的要求;与 Frank 的评论相反,Frank 认为 var 会让打字变得动态。

好吧,我很困惑,下面的代码对我来说效果很好(好奇心战胜了我!):

// Original Code Snipped for Brevity - See Edit History if Req'd

或者我错过了什么?

更新以下OP的响应

好吧,现在我真的很困惑..你的意思是你想获得一个列表 打字的 来自通用/抽象列表的值?(因此子类变得无关紧要)。

如果类型是子/接口实现者,则无法返回类型化列表 - 它们不匹配!您当然可以从抽象列表中获取特定类型的项目列表,如下所示:

    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() 来获取接口类型的列表。这应该适用于您遇到的任何情况。这有帮助吗?

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.

并且能够挑选从中产生的类型,否则如何 可以 你做吧?!我感觉你并没有真正理解泛型的意义是什么,并且你试图让它们做一些它们不是设计目的的事情!?

我最近发现了

List<A>.Cast<B>().ToList<B>()

图案。

它正是我想要的,

泛型用于静态时间类型检查 不是 运行时调度。使用继承/接口进行运行时分派,使用泛型进行编译时类型保证。

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);
    }
}

(显然,我更喜欢枚举而不是列表。)

或者 只需使用适当的动态语言(例如 VB)即可。:-)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top