Question

Il y a quelques postes déjà sur un débordement de pile sur ce genre de chose, mais pas exactement la même chose - donc des excuses à l'avance si c'est quelque chose qui a déjà été répondu

.

Pourquoi ce fonctionne pas:

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

Si je l'appelle Go () ci-dessus et passer une charge d'objets MyBase, chaque appel à Foo appellera Foo () générique qui renvoie true.

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

Pourquoi il appelle pas la version MyBase spécialisée à la place? Si je l'appelle Foo (nouveau MyBase ()) directement, il infère correctement que l'appel à faire. Est-ce à cause du manque de covariance pour les collections en C # 3, ou suis-je juste être stupide et ne pas faire cela correctement?

Merci!

Isaac

Était-ce utile?

La solution

Il ne remet pas le « spécialisé » un parce que le compilateur choisit la méthode à appeler lorsque le programme (qui, dans ce cas, est la fonction Go) est compilé , pas quand il est exécuté.

Lorsque le compilateur compile la fonction Go, la seule information dont il dispose est qu'il existe un objet de type T. Il n'a pas une idée que vous pouvez à un moment plus tard dans le temps lui fournir un objet de type MyBase. La seule option qu'il a est de choisir la surcharge de Foo<T>, et il fait cuire que pour le programme compilé.

Si vous voulez une application pour choisir les surcharges à l'exécution, et choisir la meilleure surcharge en regardant l'objet alors que l'application est en cours d'exécution, c'est appelé « expédition dynamique » et est utilisé uniquement par les langages dynamiques tels que Ruby, Python, PHP, etc.

C # 3 est entièrement statique et ne supporte pas. Il faudrait écrire un if dans votre code pour vérifier le type si on voulait travailler de cette façon. C # 4 d'autre part, a un soutien dynamique. Si vous écrivez ce code en C # 4, vous pouvez déclarer la fonction « Go » comme suit:

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

Ensuite, il utiliserait l'envoi dynamique à l'exécution de choisir lesquels la surcharge est appelé et appellerait la surcharge spécialisée pour prendre MyBase

Autres conseils

Selon les spécifications C # (7.4.3.2), la méthode non-générique est meilleur que celui générique, il devrait donc être sélectionné.

Mais, je pense que le générique est pris dans votre cas, car il est appelé dans un contexte d'invocation générique (la boucle « foreach »).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top