Changer la taille d’un tableau dans la méthode d’extension ne fonctionne pas?

Donc, fondamentalement, j’ai écrit ma petite méthode d’extension Add pour les types de tableaux.

 using System; using System.Linq; public static class Extensions { public static void Add(this T[] _self, T item) { _self = _self.Concat(new T[] { item }).ToArray(); } } public class Program { public static void Main() { ssortingng[] test = { "Hello" }; test = test.Concat(new ssortingng[] { "cruel" }).ToArray(); test.Add("but funny"); Console.WriteLine(Ssortingng.Join(" ", test) + " world"); } } 

Le résultat devrait être Hello cruel but funny world , Hello cruel but funny world , mais le but funny ne sera jamais concaténé dans la méthode d’extension.

L’édition du même tableau dans l’extension semble également ne pas fonctionner:

 using System; using System.Linq; public static class Extensions { public static void Add(this T[] _self, T item) { Array.Resize(ref _self, _self.Length + 1); _self[_self.Length - 1] = item; } } public class Program { public static void Main() { ssortingng[] test = { "Hello" }; test = test.Concat(new ssortingng[] { "cruel" }).ToArray(); test.Add("but funny"); Console.WriteLine(Ssortingng.Join(" ", test) + " world"); } } 

Qu’est-ce que je me suis trompé ici, comment puis-je l’utiliser comme extension?

Violon .dotNet: https://dotnetfiddle.net/9os8nY ou https://dotnetfiddle.net/oLfwRD

(Ce serait bien de trouver un moyen de garder le test.Add("item"); appel. test.Add("item"); )

Vous affectez une nouvelle référence à l’argument, cela ne changera pas le tableau actuel à moins que vous ne le transmettiez en tant que paramètre ref . Comme il s’agit d’une méthode d’extension, ce n’est pas une option. Alors envisagez d’utiliser une méthode normale:

 public static void Add(ref T[] _self, T item) { _self = _self.Concat(new T[] { item }).ToArray(); } Add(ref test, "but funny"); 

Ou si vous insistez sur l’utilisation de méthodes d’extension, vous devez définir le second paramètre du tableau pour pouvoir utiliser ref:

 public static void AddTo(this T item, ref T[] arr, ) { arr = arr.Concat(new T[] { item }).ToArray(); } "but funny".AddTo(ref test); 

Array.Resize ne fonctionne pas. Parce que cela change le _self , pas le tableau de test . Désormais, lorsque vous passez un type de référence sans mot-clé ref , la référence est copiée. C’est quelque chose comme ça:

 ssortingng[] arr1 = { "Hello" }; ssortingng[] arr2 = arr1; 

Maintenant, si vous assignez une nouvelle référence à arr2 , cela ne changera pas la référence de Array.Resize Ce que fait Array.Resize , c’est que puisque le redimensionnement d’un tableau n’est pas possible, il crée un nouveau tableau et copie tous les éléments dans un nouveau tableau et il assigne cette nouvelle référence au paramètre ( _self dans ce cas). arr1 , le arr2 arr1 arr2 mais étant donné que _self et test sont deux références différentes (comme arr1 et arr2 ), la modification de l’une n’affecte pas l’autre.

Par ailleurs, si vous transmettez un tableau en tant que ref à votre méthode, comme dans mon premier exemple, Array.Resize fonctionnera également comme prévu, car dans ce cas, la référence ne sera pas copiée:

 public static void Add(ref T[] _self, T item) { Array.Resize(ref _self, _self.Length + 1); _self[_self.Length - 1] = item; } 

Je pense que _self = crée une copie de l’object _self dans la variable locale créée pour le paramètre _self – et que l’original ne sera pas mis à jour. Utilisez un type de référence comme une liste ou créez une méthode statique qui renvoie le nouveau tableau.

En termes de “sensation” de la raison: vous appelez une méthode sur une instance variable – vous ne pouvez pas modifier cette instance à partir du code s’exécutant dans le contexte correspondant

Vous pouvez changer le code comme ceci:

 public static class Extensions { public static T[] Add(this T[] _self, T item) { return _self.Concat(new T[] { item }).ToArray(); } } public class Program { public static void Main() { ssortingng[] test = { "Hello" }; test = test.Concat(new ssortingng[] { "cruel" }).ToArray(); test = test.Add("but funny"); Console.WriteLine(Ssortingng.Join(" ", test) + " world"); } } 

En remarque, l’utilisation sera identique à la méthode Concat.