7
votes

Fonction ambiguë / constructeur appeler C #

Le code suivant provoque une erreur de compilateur, car il est un appel ambigu, mais le problème si nous utilisons objet code> au lieu de ArrayList code> Aucune erreur ne se produit et la chaîne la version fonctionne bien; Avez-vous une explication pour cela?

class A
{
    public A(string x)
    {
        Console.WriteLine("string");
    }
    public A(ArrayList x)
    {
        Console.WriteLine("ArrayList");
    }

}
    static void Main(string[] args)
        {
            A o = new A(null);
        }


3 commentaires

Je suis sûr que quelqu'un postera une meilleure explication que possible, mais il est inutile de dire que vous devriez probablement éviter ce modèle et mettre en œuvre un constructeur par défaut. Oh, attends, je l'ai dit ...


Quelle version de .NET utilisez-vous? Parce que si vous utilisez 2.0 ou plus, vous pouvez utiliser un ou toute autre collection qui convient le mieux à votre situation? La mise en œuvre d'un constructeur par défaut pourrait également aider.


@Will Marcouiller: .NET 3.5 Mais je m'interroge sur le comportement lui-même c'est un exemple


6 Réponses :


3
votes

NULL pourrait représenter soit une chaîne String , soit un arrayliste . Il n'y a aucune information il n'y a que dans quelle version de la méthode (dans ce cas un constructeur) que vous vouliez dire.

Vous pouvez le forcer à utiliser un spécifique par casting: xxx

... ou dans la mise en œuvre alternativement d'un constructeur qui se comporte comme vous le souhaitez (qui ne prend aucun paramètre)


2 commentaires

Un objet pourrait être null aussi, mais l'OP a indiqué que la modification de la liste TRAYLIST sur objet résout le problème; Donc, ce n'est pas la photo entière. Le vrai problème est que dans ce cas, aucun type ne sera "gagnant" dans les yeux du compilateur car on n'hérite pas de l'autre. Dans le cas de string vs. objet , string gagne car il dérive à partir de objet et est donc plus spécifique .


Qu'en est-il de l'utilisation de l'objet, vous n'avez pas répondu



1
votes
  1. Bien sûr, il est ambigu: null pourrait être un chaîne ou un tableau arraylist . Vous aurez besoin de le qualifier, comme (string) null .
  2. Saviez-vous que ArrayList est obsolète? Vous devez utiliser l'un des types de collecte génériques à la place

5 commentaires

Pour le tableau, cela dépend de la version du cadre qu'il utilise, je suppose. Mais bon point pour le null ambiguïté.


@Will: S'il utilise toujours .net 1.1, je lui dirais que .NET 1.1 a été obsolète.


Hehehe ... juste! =) Mais parfois, on doit traiter des décisions administratives. Si ce n'est pas cassé, ne le répare pas! Mais pourtant, je reçois ton point de toute façon. =)


J'ai mis l'arraylist comme exemple que j'utilise .NET 3.5


ArrayList est une classe que vous ne devriez plus utiliser. Le remplacement direct est list .



4
votes

Je pourrais avoir tort, mais je pense que la raison pour laquelle il fonctionne lorsque vous modifiez une arraylist en objet, c'est parce que la chaîne hérite de l'objet et il décide d'utiliser la version de chaîne plus spécifique. Quand c'est une chaîne et une arraylist, il ne sait pas lequel à utiliser.


0 commentaires

16
votes

La raison pour laquelle votre code fonctionne bien si vous modifiez le constructeur qui prend un Arraylist pour prendre un objet est que le compilateur C # choisira le type le plus spécifique applicable. Dans le cas de chaîne / objet , string réellement dérive de objet et est donc "plus spécifique" et sera déduit par le compilateur. Avec chaîne Versus ArrayList , c'est des pommes et des oranges: soit NULL, mais non plus "spécifique" que l'autre.


4 commentaires

+1 me bat à l'explication. Votre réponse est la seule qui répond à la question réelle.


Ligne du jour: C'est des pommes et des oranges: soit NULL, mais non plus "spécifique" que l'autre. :)


@THEMACHINCHARMER: Quoi, vous n'avez jamais mangé une pomme nulle? Ils sont delicieux.


NON. Il n'y avait que 4 pommes nulles. Et ils étaient tous consommés par Adam, Isaac Newton, Steve Jobs et vous! (chronologiquement) :) lol



1
votes

arraylist et string sont tous deux nullable Types. Qui confond compilateur.

Si vous avez deux constructeurs, dit celui qui prend un type nullable par exemple. ArrayList et d'autre qui prend non nullable type E.G. int . Le code compilera et choisira le constructeur avec Nullable type.

mais si vous avez plus qu'un constructeur qui prend nullable type, alors comme @ Dan Tao dit C'est des pommes et des oranges: soit NULL, mais non plus" spécifique "que l'autre.

Par exemple: xxx

Ce code compile Mais si vous changez public a (int x) t sur public a (int? x) Ce ne sera pas.


3 commentaires

Ce n'est pas vraiment à faire avec eux étant nullable \ types de référence, mais plutôt qu'il n'y a pas d'option «meilleure» de choisir entre chaîne et arraylist. Si vous aviez une fonction avec une surcharge prenant un flux et que vous preniez un mémoire Morthstream et l'a appelé avec NULL, le compilateur serait capable de le résoudre.


@Lee merci! Mais pourriez-vous s'il vous plaît expliquer comment le compilateur la résout dans ce cas?


Cet article d'Eric Lippert explique mieux la résolution de surcharge que moi - Stackoverflow.com/Questtions/2856023/... .



2
votes

Vous pouvez vous attaquer à cette situation en utilisant le mot-clé défaut comme et le code sera le suivant: xxx

ou xxx


0 commentaires