Pergunta

Existem alguns lugares já no estouro de pilha sobre esse tipo de coisa, mas não exatamente o mesmo - assim desculpas antecipadamente se isso é algo que já foi respondida

.

Por que isso não funciona:

public class MyBase { }

public class MyUtils
{
    public bool Foo<T> (T myObject) { return true; }
    public bool Foo (MyBase myBaseObject) { return false; }

    public void Go<T> (IEnumerable<T> items)
    {
        foreach (var item in items)
        {
            // this test fails
            Assert.IsFalse (Foo (item));
        }
    }
}

Se eu chamar Go () acima e passar uma carga de MyBase objetos, cada chamada para Foo irá chamar o Foo genérico (), que retorna verdadeiro.

new MyUtils ().Go (new MyBase[] { new MyBase (), new MyBase () });      

Por que não chamar a versão MyBase especializada em vez disso? Se eu chamar Foo (novo MyBase ()) diretamente, ele corretamente infere que chamada para fazer. Isso é por causa da falta de covariância para coleções em C # 3, ou estou apenas sendo boba e não fazendo isso corretamente?

Obrigado!

Isaac

Foi útil?

Solução

Ele não chama a um "especializada", porque os choses compilador qual método chamar quando o programa (que, neste caso, é a função Go) é compilado , não quando ele é executado.

Quando o compilador é compilar a função Go, a única informação que tem é que há algum objeto do tipo T. Ele não tem qualquer idéia que você pode em algum momento posterior fornecê-lo com um objeto do tipo MyBase. A única opção que tem é escolher a sobrecarga Foo<T>, e assim que coze que para o programa compilado.

Se você quiser um aplicativo para escolher sobrecargas em tempo de execução, e escolher o melhor sobrecarga, olhando para o objeto enquanto o aplicativo é executado, que é chamado de "expedição dinâmica", e é usado somente por linguagens dinâmicas como Ruby, Python, PHP, etc.

C # 3 é totalmente estática e não suporta isso. Você teria que escrever uma instrução if no seu código para verificar o tipo se você queria para trabalhar desta forma. C # 4, por outro lado, tem algum suporte dinâmico. Se você estivesse escrevendo este código em C # 4, você poderia declarar a função 'Go' da seguinte forma:

 public void Go<T> (IEnumerable<dynamic> items)

Em seguida, ele iria usar expedição dinâmica em tempo de execução para escolher qual sobrecarga é chamado, e chamaria a sobrecarga especializada para tirar MyBase

Outras dicas

De acordo com as especificações C # (7.4.3.2), o método não-genérico é melhor do que o genérico, por isso deve ser selecionado.

Mas, eu acho que o genérico é captado no seu caso, porque ele é chamado dentro de um contexto de invocação genérica (o "foreach" loop).

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