1

我有以下代码

class Program
    {
        static void Main(string[] args)
        {
            List<A> aList = new List<A>();

            var aObj = new A();

            aObj.Go(aList.Cast<IB>());
        }
    }

    class A : IB
    {
        public void Go(IEnumerable<IB> interfaceList)
        {
            foreach (IB ibby in interfaceList)
            {
                Console.WriteLine("Here");
            }
        }
    }

    interface IB
    {
        void Go(IEnumerable<IB> interfaceList);
    }

}

我最初尝试传递一个 List 但这不起作用。经过SO的大量帮助后,我发现传递 IEnumerable 是将对象作为 .ofType(IB) 传递的唯一方法。

对我来说不幸的是,在我的代码中,以下行将被执行数千次:

aList.Cast<IB>();

我想知道是否有人知道它是如何通过算法实现的(在 IL 中)以及它的时间顺序是什么。

也就是说,它是否比只强制转换每个项目的 foreach 循环更快,或者这正是它的作用?

编辑主类需要维护一个实际对象的列表。但读者只能通过界面触摸它们。

4

6 回答 6

10

您应该更改Go为:

public void Go<T>(IEnumerable<T> interfaceList)
    where T : IB
{
    foreach (IB ibby in interfaceList)
    {
        Console.WriteLine("Here");
    }
}

然后你就可以不用打电话了Cast。我怀疑 Cast 的源代码实现非常简单,尽管我相信它在 3.5 和 3.5SP1 之间发生了变化。但是,它可能需要以正常的迭代器块方式设置新的状态机等。如果可能,最好避免它。

尽管新方法是通用的,但类型推断通常应该为您处理好它,因此您无需T显式指定。

于 2009-03-03T15:48:54.740 回答
5

为什么不像这样声明列表:

List<IB> aList = new List<IB>();

有什么特别需要你列出具体类的吗?


因此,在这种情况下,我会将列表作为域的一部分。拥有像 IIBCollection 这样的接口(例如),公开您希望读者能够访问的方法。例如:

interface IIBCollection{
    IEnumerable<IB> IBs { get; }
}

// and in your implementation you can do

IEnumerable<IB> IBs { 
    get { 
        foreach(IB ib in innerList) yield return ib; 
}}
于 2009-03-03T15:49:09.607 回答
1

它在内部实现为 CastIterator,它比强制转换每个项目的 foreach 稍慢。

于 2009-03-03T15:49:33.693 回答
0

Cast 方法只会遍历列表并转换每个项目。

如果您要使用列表数千次,只需将转换结果存储为列表即可。

如果这是不可能的(即您每次都更改列表),请考虑使用 aList<IB>而不是 a List<A>

于 2009-03-03T15:53:57.723 回答
0

这不是 C# 中的协方差的用途吗?我看不到您要做什么,所以我无法评论为什么它被执行了数千次。

于 2009-03-03T15:54:48.250 回答
0

只需对这两种方法(Cast 扩展方法和带有强制转换的 for 循环)进行基准测试,这将是一件相当简单的事情。但是鉴于 Cast 是 Enumerable 类的扩展方法并且一般处理 IEnumerables,我想这正是它的实现。如果您想要最快的速度,最好实现您自己的专门用于 List 的扩展方法(通过其索引获取每个元素),考虑到迭代器的开销,这应该会稍微快一些。尽管如此,这两种方法都应该花费 O(n) 时间,所以差异应该不会很大。尽管如此,这是值得进行基准测试的东西......

于 2009-03-03T15:56:10.977 回答