2 votes

Retourner un tableau à partir d'une méthode C#

Je me suis demandé pourquoi ma méthode ne modifiait pas le tableau, alors que je l'ai utilisé comme paramètre et l'ai rendu égal à un autre tableau avec des valeurs différentes, à l'intérieur de la méthode ? Est-ce que je change simplement l'adresse de référence ?

    static void Main()
    {
        string[] array = { "yes", "no", "maybe" };
        TestO(array); // Still "yes", "no", "maybe"
    }

    static void TestO(string[] array)
    {
        string[] secondArray = new string[array.Length]; 
        secondArray[0] = "1";
        secondArray[1] = "2";
        secondArray[2] = "3";
        array = secondArray; 
    }

Mon hypothèse : je n'ai pas modifié le tableau à l'intérieur de Main(), car en faisant array = secondArray; dans le Test0() méthode, Je viens de changer l'adresse de référence de array a secondArray .

Si ma supposition n'est pas correcte, ma question est la suivante : pourquoi exactement n'est-il pas modifié ?

(Je sais que je peux simplement modifier Test0() à un string[] et renvoie la version modifiée de la secondArray et la transmettre à l array en Main() )

Une autre question se pose : Si j'utilise le string[] et déclarer ce qui suit :

        static void Main()
    {
        string[] array = { "yes", "no", "maybe" };
        array = TestO(array); 
    }

    static string[] TestO(string[] methodArray)
    {
        string[] secondArray = new string[methodArray.Length];
        secondArray[0] = "1";
        secondArray[1] = "2";
        secondArray[2] = "3";
        return secondArray; 
    }

array = TestO(array); est-ce que je passe simplement l'adresse de référence du secondArray[] a array[] ou est-ce que je ne transmets que les valeurs de l'élément ? (Il est très probable que ce soit l'adresse de référence, mais je voulais m'en assurer).

3voto

Caius Jard Points 212

Je viens de changer l'adresse de référence du tableau en secondArray. Si ma supposition n'est pas correcte, ma question est la suivante : pourquoi exactement le tableau n'est-il pas modifié ?

Je pense que vous êtes en train de comprendre qu'il y a deux références à une donnée en mémoire (il n'y a pas deux données) ; vous avez une variable array qui renvoie à des données. Vous appelez une méthode et une autre référence copiée est établie sur les mêmes données. Vous avez créé un nouvel objet, puis vous avez pointé la référence copiée vers le nouvel objet, laissant la référence originale pointer vers les données originales, puis vous avez jeté la référence copiée et les nouvelles données Vous vous retrouvez dans la même situation qu'au début.

De manière imagée, ligne par ligne, cela pourrait ressembler à (j'ai renommé l'argument de votre méthode en arrayX la différence est donc évidente) :

enter image description here

Si vous décorez l'argument avec ref et le suivre avec ref il n'y a pas de copie, de sorte que la méthode appelée peut modifier la référence originale et la faire pointer ailleurs :

enter image description here

Il convient de noter qu'en soit dans ces cas, il est tout à fait possible de modifier la contenu du tableau. Faire :

arrayX[0] = "New data";

prendrait effet en soit boîtier et impression array[0] afficherait "Nouvelles données". Lors de la modification des données à l'extrémité de la flèche, il importe peu que le point de départ soit une référence originale ou une copie. Il s'agit de purement la question de savoir si la méthode a le pouvoir de faire pointer la référence originale qui lui a été transmise vers un objet différent ou non.

En général, nous ne le faire. Nous adoptons le style de votre deuxième bloc de code - pour renvoyer les données. Il peut être utile de voir cela comme une impolitesse - imaginez que votre ami vous dise qu'il s'occupera de votre plante pendant que vous êtes en vacances ; vous donnez vos clés à votre ami. Il échange votre plante contre une autre qu'il préfère ; vous êtes contrarié parce que vous aviez cette plante depuis dix ans .

Il y a très peu de raisons d'utiliser ref ou le "pouvoir d'annuler votre référence" - out . Ne l'utilisez pas pour "Je voulais renvoyer plusieurs choses de ma méthode" - dans un monde OO, nous pouvons toujours renvoyer une chose qui représente deux éléments de données. Nous n'avons pas besoin de "renvoyer deux choses" ; nous pouvons renvoyer une chose avec deux choses à l'intérieur...

//don't:
void GetPerson(ref string name, ref int age)

//consider a class:
Person GetPerson()
  return new Person(){ Name = ..., Age = ...}

//or a Tuple
(string Name, int Age) GetPerson

Laisser la méthode appelante choisir si sa propre variable doit être écrasée, plutôt que de laisser une "tierce partie" tirer le tapis sous ses pieds.

2voto

Serge Points 7425

Il n'est pas nécessaire de renvoyer quoi que ce soit, il suffit d'utiliser un ref

static void Test( ref string[] array)
    {
        string[] secondArray = new string[array.Length]; 
        secondArray[0] = "1";
        secondArray[1] = "2";
        secondArray[2] = "3";
        array = secondArray; 
    }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X