Pergunta

Eu tenho o seguinte código

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

}

Inicialmente eu tentei passar uma lista, mas que não funciona . Depois de muita ajuda de descobri que passar IEnumerable é o única maneira de obter os objetos transversalmente como .ofType (IB).

milhares Infelizmente para mim, no meu código a seguinte linha serão executados de vezes:

aList.Cast<IB>();

Eu queria saber se alguém sabia como ele foi implementado através de algoritmos (em IL) e qual o seu fim é o tempo.

Ou seja, é mais rápido do que um loop foreach que só lança cada item, ou isso é exatamente o que ele faz?

As principais necessidades de classe Editar para manter uma lista dos objetos reais. Mas o leitor só é permitido para tocá-los através da interface.

Foi útil?

Solução

Você deve alterar Go a:

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

Em seguida, você vai ficar bem sem a necessidade de Cast chamada. Eu suspeito que a implementação de código fonte de Cast é bastante simples, embora eu acredite que mudou entre 3,5 e 3.5SP1. No entanto, provavelmente precisa de configurar uma nova máquina de estado etc na forma normal bloco iterador. Melhor para evitá-lo, se possível.

Mesmo que o novo método é genérico, inferência de tipos geralmente deve cuidar dele para você, assim você não precisa especificar T explicitamente.

Outras dicas

Porque não basta declarar a lista como:

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

Há alguma coisa em particular que exige que você tenha uma lista das classes concretas?


Então, nesse caso eu faria a parte lista do domínio. Possui uma interface como IIBCollection (por exemplo), expor os métodos em que você quer que o leitor seja capaz de acessar. Por exemplo:

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

Ele é implementado internamente como um CastIterator que é ligeiramente mais lento do que um foreach que lança cada item.

O método Elenco só vai percorrer a lista e lançar cada item.

Se você estiver indo para usar a lista de milhares de tempo, apenas armazenar o resultado da fundição como uma lista.

Se isso não for possível (ou seja, alterar a lista de cada vez), considere trabalhar com um List<IB> em vez de um List<A>.

Não é isso que covariância em C # é para? Eu não vejo o que você está tentando fazer, então eu não posso comentar sobre milhares por isso que é exeuted e milhares de vezes.

Seria uma questão bastante simples apenas para referência a dois métodos (método de extensão Cast e um loop com um elenco). Mas dado que Cast é um método de extensão da classe Enumerable e trata genericamente com IEnumerables, eu imagino este é precisamente a sua implementação. Se você quiser a maior velocidade, pode ser melhor para implementar seu próprio método de extensão que funciona especificamente sobre List (fica cada elemento por seu índice), que deve ser um pouco mais rápido dada a sobrecarga de iteradores. Ainda assim, ambos os métodos devem tomar tempo O (n), de modo que a diferença não deve ser enorme. É algo que vale a pena benchmarking, no entanto ...

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top