7
votes

Liste in c #

Je suis incapable de comprendre la logique derrière Liste car il casse une partie des règles de base.

Liste est censé être de type de valeur et non de type de référence.

  1. Liste doit être transmis par ref mot-clé si sa valeur doit être persistée entre les appels de fonction. Cela signifie donc qu'il affiche un comportement de type de valeur similaire à INT.
  2. mais list doit être initialisé par un nouvel opérateur. Aussi Liste pourrait être aussi null. Cela implique un comportement de type de référence.

    Un type nullable est différent, car il n'est pas nécessaire d'être initialisé par nouvel opérateur.

    Suis je vois quelque chose ne va pas ici?

    éditéd-

    J'aurais dû poster le code dans la question initiale elle-même. Mais il suit ici - xxx


8 commentaires

Que voulez-vous dire exactement avec votre point 1? Pourriez-vous donner un exemple pourquoi vous pensez avoir besoin de ref ?


@ 0xa3 => Créer une méthode1 qui prend la liste comme paramètre. Ensuite, dans la méthode de la méthode principale 1 une liste . Dans la méthode1, ajoutez des entiers à la liste. Dans la méthode principale, voir si vous obtenez ces entiers de retour.


MattMC3 a déjà posté un exemple comme celui-ci démontrant que vous n'avez pas besoin ref .


En ce qui concerne votre code, le problème est que vous attribuez une nouvelle liste . Le code extérieur ne voit pas la nouvelle liste - mais si vous avez modifié la liste d'origine, cela verrait ces changements.


@Anon => Que voulez-vous dire par code extérieur ne voit pas la nouvelle liste?. Pouvez-vous s'il vous plaît élaborer.


@Prashant: Supposons que vous ayez une maison et une carte postale qui vous indique l'adresse de la maison. Vous copiez cette carte postale et donnez la copie à quelqu'un. S'ils vont à la maison et le changent, tous les autres verront la maison changée, mais s'ils construisent une nouvelle maison et gribouent de son adresse sur leur carte postale, cela n'affectera personne d'autre.


@Prashant - Je pense que @Anon essaie de décrire est que les variables détenant des types de référence contiennent simplement une référence à un emplacement en mémoire sur le tas. Ainsi, «L 'dans la méthode« Modiyit' »commence à désactiver le même emplacement que« LISTISAREFTYPE », mais obtient ensuite son adresse modifiée par l'appel vers« Nouvelle liste () 'et l'élément est ajouté à cette liste. .. 'LISTAREFTYPE' signifie toujours à l'emplacement d'origine - qui reste une liste vide. Belle question - m'a pris un moment pour l'obtenir! ;-)


Liste n'est pas un type de valeur.


9 Réponses :


30
votes
La liste

est censée être de type de valeur et non de type de référence.

mauvais! int est un type de valeur. Liste est un type de référence.


4 commentaires

Si c'était le cas, pourquoi réussir la liste entre les fonctions?


@Prash vous feriez cela si vous vouliez modifier la référence elle-même (c.-à-d.: Définissez-la sur NULL ou une liste différente). Mais je ne construirais pas normalement le code pour que cela soit nécessaire.


@Prastant: Vous n'avez pas besoin de. Quiconque vous a dit que vous faites, c'est toujours un crétin. Ce que le mot clé ref est, vous permet de définir le paramètre sur une autre liste . Ce qui n'est même pas aussi commun que vous semblez penser que c'est.


Pauvre, ancien ref ; tellement mal compris. :)



2
votes

Liste code> est en effet un type de référence. Mais les éléments contenus dans la liste sont des types de valeur.

Les types nullables sont toutefois implémentés comme des structures ( structure nullable où T: struct code>) et sont donc des types de valeur. La raison pour laquelle vous pouvez simplement écrire p> xxx pré>

sans le mot clé code> nouveau code> est que la syntaxe ci-dessus est traduite automatiquement par le code qui fera le code qui fera la Suivant: p>

Nullable<Int32> i = new Nullable<Int32>(3);


0 commentaires

1
votes

A Liste est un type de référence générique, vous l'utilisez avec une valeur de type int. Mais c'est toujours un type de référence.


0 commentaires

2
votes

ne pense pas à cela comme Liste pense à cela comme il a été écrit Liste .

liste est une classe générique . Ce n'est pas une structure. C'est une classe générique pouvant fonctionner avec des types de valeur et des types de référence.


0 commentaires

0
votes

Liste est un type de référence. Et il n'est pas nécessaire d'être transmis comme une référence.

Le type des objets in la liste est une sorte de type de valeur, à l'exception des objets de type de valeur peuvent se retrouver en boîte (converti en objets de type de référence d'une sorte) de toute façon, donc ..cratch ce paragraphe une fois que vous comprenez cela.


2 commentaires

Notez que Liste pas nécessite une boxe. Seulement si vous placez une valeur de type dans une liste la boxe sera impliquée.


@ 0xa3: Je n'étais pas sûr de la façon dont la merde .net l'a fait. Je sais que Java est agaçant à ce sujet, mais ses entiers sont une tentative à moitié construite de faire ressembler des primitives à ressembler à des objets, alors que les "primitives" de .NET sont des objets réels.



7
votes

Je pense que vous avez une hypothèse défectueuse dans votre première balle. L'objet de liste générique est définitivement un type de référence (sur le tas, pas la pile). Je ne sais pas pourquoi vous pensez que vous devez passer via ref code>. Ceci imprime "2" comme il devrait:

namespace ConsoleApplication1 {
   class Program {
      static void Main(string[] args) {
         List<int> listIsARefType = new List<int>();
         ModifyIt(listIsARefType);
         ModifyIt(listIsARefType);
         Console.WriteLine(listIsARefType.Count); // 2!
         Console.ReadKey(true);
      }

      static void ModifyIt(List<int> l) {
         l.Add(0);
      }
   }
}


1 commentaires

Je pense qu'il est important de noter que toute liste est un type de référence en raison du fait qu'il a été créé à partir d'un basetie qui est un type de référence. Il convient de noter qu'un élément figurant dans la liste est potentiellement pas un type de référence, mais cela pourrait devenir un type de référence.



6
votes

Vous devez comprendre la différence entre passer par référence em>, passer par valeur em> et transmettez-la par valeur em>.

dans le Code Sample Vous avez publié, vous passez la em> référence em> à la liste code> objet par valeur em>. Cela signifie que vous pouvez muter l'objet indiqué par la référence, et le code d'appel verra ces modifications. Cependant, la référence elle-même est transmise par valeur, de sorte que si vous modifiez la référence à un objet différent à un objet différent, le code d'appel ne verra pas les modifications. P>

Lorsque vous utilisez le ref Code> Mot clé, vous passez la référence elle-même par référence. Cela signifie que non seulement vous pouvez modifier l'objet que la référence indique, mais vous pouvez également modifier la référence elle-même. P>

considère cet exemple: p>

class Program
{
    static void Main()
    {
        int foo = 0;
        DoSomething1(foo);
        Console.WriteLine(foo); // Outputs 0.

        DoSomething1(ref foo);
        Console.WriteLine(foo); // Outputs 1.

        var bar = new List<int>();
        DoSomething2(bar);
        Console.WriteLine(bar.Count); // Outputs 1.

        DoSomething2(ref bar);
        Console.WriteLine(bar.Count); // Outputs 0.
    }

    // Pass by value.
    static void DoSomething1(int number)
    {
        // Can't modify the number!
        number++;
    }

    // Pass by value.
    static void DoSomething1(ref int number)
    {
        // Can modify the number!
        number++;
    }

    // Pass reference by value.
    static void DoSomething2(List<int> list)
    {
        // Can't change the reference, but can mutate the object.
        list.Add(25);
    }

    // Pass reference by reference.
    static void DoSomething2(ref List<int> list)
    {
        // Can change the reference (and mutate the object).
        list = new List<int>();
    }
}


0 commentaires

1
votes

En plus des hypothèses erronées traitées dans d'autres réponses, vous dites:

Liste doit être initialisé par un nouvel opérateur ... cela implique un Comportement de type de référence.

Non, en C # L'opérateur Nouveau n'est que la syntaxe pour appeler le constructeur d'un type. Il est utilisé pour les types de valeur de référence et définis par l'utilisateur ( struct s).


0 commentaires

0
votes

dans la méthode ModifyIt (), lorsque vous écrivez 'l = retourliste ()'; 'L' est maintenant dirigé vers un emplacement différent de la mémoire que celle de LISTISAREFTYPE dans votre méthode Test (). Fondamentalement, en écrivant "L" "=" quelque chose, vous avez enfreint le lien entre "L" et "LISISAREFTYPE". Afin de conserver le lien (qui assure que les deux objets, "L" et "LissiSareftype" pointant vers le même emplacement dans la mémoire), vous devez seulement travailler sur l'objet "L" (par exemple En appelant une fonction sur l'objet), ou utilisez le mot-clé ref dans le paramètre de la méthode ModifyIt ().


0 commentaires