列出<T>投射算法和性能注意事项

Dev*_*inB 1 c# performance casting generic-list

我有以下代码

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);
    }
Run Code Online (Sandbox Code Playgroud)

}

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

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

aList.Cast<IB>();
Run Code Online (Sandbox Code Playgroud)

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

也就是说,它是否比仅仅投射每个项目的foreach循环更快,还是它正是它的作用?

编辑主类需要维护实际对象的列表.但是只允许读者通过界面触摸它们.

Jon*_*eet 10

你应该Go改为:

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

然后你会好起来的,不需要打电话Cast.我怀疑Cast的源代码实现非常简单,虽然我认为它在3.5和3.5SP1之间变化.但是,它可能需要以正常的迭代器块方式设置新的状态机等.如果可能的话,最好避免它.

尽管新方法是通用的,但类型推断通常应该为您处理,因此您不需要T明确指定.


jon*_*nii 5

为什么不直接声明列表:

List<IB> aList = new List<IB>();
Run Code Online (Sandbox Code Playgroud)

有什么特别要求你有一个具体类的列表?


所以在这种情况下,我会将列表作为域的一部分.有一个像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; 
}}
Run Code Online (Sandbox Code Playgroud)