Existe-t-il une meilleure façon (voir ci-dessous) d'ajouter des tableaux de deux octets en C #?
En faisant semblant d'avoir un contrôle complet, je peux rendre le premier tableau d'octets suffisamment grand pour contenir le second tableau d'octets à la fin et utiliser la fonction Array.CopyTo . Ou je peux boucler sur des octets individuels et faire une affectation.
Y a-t-il de meilleures façons? Je ne peux pas imaginer faire quelque chose comme convertir les tableaux d'octets en chaîne et les joindre et les reconvertir serait mieux que l'une ou l'autre méthode ci-dessus.
En termes de meilleur/meilleur (dans l'ordre):
Une contrainte est que je dois travailler dans le framework .NET 2.0.
Les deux choix recommandés sont MemoryStream et BlockCopy. J'ai exécuté un test de vitesse simple de 10 000 000 boucles 3 fois et j'ai obtenu les résultats suivants:
Résultats de la liste <byte> AddRange plus de 10 millions de boucles: List <byte> Durée: 16694
Le test montre qu'en général, à moins que vous ne fassiez beaucoup de copies d'octets [ que je suis ], regarder des copies d'octets ne vaut pas la peine d'être ciblé [ par exemple 10 millions d'exécutions, ce qui représente une différence pouvant atteindre 1,1 seconde].
Vous voulez BlockCopy
Selon ce billet de blog c'est plus rapide que Array.CopyTo.
Vous pouvez également utiliser une approche avec un MemoryStream. Supposons que b1 et b2 soient des tableaux à deux octets, vous pouvez en obtenir un nouveau, b3, en utilisant le MemoryStream de la manière suivante:
var s = new MemoryStream();
s.Write(b1, 0, b1.Length);
s.Write(b2, 0, b2.Length);
var b3 = s.ToArray();
Cela devrait fonctionner sans LINQ et est en fait un peu plus rapide.
Créez un nouveau MemoryStream en passant dans le constructeur un tampon qui est exactement la taille de celui fusionné. Écrivez les tableaux individuels, puis utilisez enfin le tampon:
byte[] deadBeef = new byte[] { 0xDE, 0xAD, 0xBE, 0xEF};
byte[] baadF00d = new byte[] { 0xBA, 0xAD, 0xF0, 0x0D};
int newSize = deadBeef.Length + baadF00d.Length;
var ms = new MemoryStream(new byte[newSize], 0, newSize, true, true);
ms.Write(deadBeef, 0, deadBeef.Length);
ms.Write(baadF00d, 0, baadF00d.Length);
byte[] merged = ms.GetBuffer();
De nombreuses fonctions d'E/S de bas niveau dans .NET prennent des tableaux d'octets et des décalages. Cela a été fait pour éviter les copies inutiles. Assurez-vous que vous avez vraiment besoin du tableau fusionné si cela est sensible aux performances, sinon utilisez simplement des tampons et des décalages.
Une autre option, même si je ne l'ai pas testée pour voir comment elle se porte en termes de vitesse et de consommation de mémoire, serait l'approche LINQ:
byte[] combined = bytesOne.Concat(bytesTwo).Concat(bytesThree).ToArray();
... où bytesOne, bytesTwo et bytesThree sont des tableaux d'octets. Étant donné que Concat utilise une exécution différée, cela ne doit pas créer de tableaux intermédiaires et ne doit pas dupliquer les tableaux d'origine jusqu'à ce qu'il construise le tableau fusionné final à la fin.
Edit: LINQBridge vous permettra d'utiliser LINQ-to-Objects (dont ceci est un exemple) dans le framework 2.0. Je comprends si vous ne voulez pas en dépendre, mais c'est une option.
Si vous avez des tableaux dont la taille changera de temps en temps, vous feriez probablement mieux d'utiliser un List<T>
En premier lieu. Ensuite, vous pouvez simplement appeler la méthode AddRange()
de la liste.
Sinon, Array.Copy () ou Array.CopyTo () sont aussi bons que tout ce que vous verrez probablement.
Avez-vous besoin que la sortie soit réellement un tableau d'octets?
Sinon, vous pouvez créer vous-même un "curseur intelligent" (qui est similaire à ce que fait LINQ): créez un IEnumerator personnalisé <octet> qui itérera d'abord le premier tableau, et continuera simplement sur le second sans interruption.
Cela fonctionnerait dans le cadre 2.0 serait rapide (en ce que la jonction des tableaux n'a pratiquement aucun coût), et n'utiliserait pas plus RAM que les tableaux consomment déjà.
Avez-vous appris à utiliser List ou ArrayList au lieu d'un tableau? Avec ces types, ils peuvent s'agrandir ou se réduire et s'ajouter via InsertRange
Votre première option consistant à créer le premier tableau suffisamment grand pour contenir le deuxième tableau et à utiliser Array.CopyTo finit par être à peu près la même que d'itérer manuellement sur chaque élément et de faire l'affectation. Array.CopyTo () le rend simplement plus concis.
La conversion en chaîne et retour en tableau sera horriblement lente contrairement à ce qui précède. Et utiliserait probablement plus de mémoire.