Je travaille sur un formulaire Windows pour calculer UPC pour les numéros d'articles.
J'ai réussi à en créer un qui gérera un numéro d'article/UPC à la fois, maintenant je veux développer et le faire pour plusieurs numéros d'article/UPC.
J'ai commencé et essayé d'utiliser une liste, mais je reste bloqué. J'ai créé une classe d'aide:
public class Codes
{
private string incrementedNumber;
private string checkDigit;
private string wholeNumber;
private string wholeCodeNumber;
private string itemNumber;
public Codes(string itemNumber, string incrementedNumber, string checkDigit, string wholeNumber, string wholeCodeNumber)
{
this.incrementedNumber = incrementedNumber;
this.checkDigit = checkDigit;
this.wholeNumber = wholeNumber;
this.wholeCodeNumber = wholeCodeNumber;
this.itemNumber = itemNumber;
}
public string ItemNumber
{
get { return itemNumber; }
set { itemNumber = value; }
}
public string IncrementedNumber
{
get { return incrementedNumber; }
set { incrementedNumber = value; }
}
public string CheckDigit
{
get { return checkDigit; }
set { checkDigit = value; }
}
public string WholeNumber
{
get { return wholeNumber; }
set { wholeNumber = value; }
}
public string WholeCodeNumber
{
get { return wholeCodeNumber; }
set { wholeCodeNumber = value; }
}
}
Ensuite, j'ai commencé avec mon code, mais le problème est que le processus est incrémentiel, ce qui signifie que j'obtiens le numéro d'article d'une vue de grille via des cases à cocher et que je les mets dans la liste. Ensuite, j'obtiens le dernier UPC de la base de données, supprime le chiffre de contrôle, puis incrémente le nombre de un et le mets dans la liste. Ensuite, je calcule le chiffre de contrôle pour le nouveau numéro et le mets dans le Et là, je reçois déjà une exception de mémoire insuffisante. Voici le code que j'ai jusqu'à présent:
List<Codes> ItemNumberList = new List<Codes>();
private void buttonSearch2_Click(object sender, EventArgs e)
{
//Fill the datasets
this.immasterTableAdapter.FillByWildcard(this.alereDataSet.immaster, (textBox5.Text));
this.upccodeTableAdapter.FillByWildcard(this.hangtagDataSet.upccode, (textBox5.Text));
this.uPCTableAdapter.Fill(this.uPCDataSet.UPC);
string searchFor = textBox5.Text;
int results = 0;
DataRow[] returnedRows;
returnedRows = uPCDataSet.Tables["UPC"].Select("ItemNumber = '" + searchFor + "2'");
results = returnedRows.Length;
if (results > 0)
{
MessageBox.Show("This item number already exists!");
textBox5.Clear();
//clearGrids();
}
else
{
//textBox4.Text = dataGridView1.Rows[0].Cells[1].Value.ToString();
MessageBox.Show("Item number is unique.");
}
}
public void checkMarks()
{
for (int i = 0; i < dataGridView7.Rows.Count; i++)
{
if ((bool)dataGridView7.Rows[i].Cells[3].FormattedValue)
{
{
ItemNumberList.Add(new Codes(dataGridView7.Rows[i].Cells[0].Value.ToString(), "", "", "", ""));
}
}
}
}
public void multiValue1()
{
_value = uPCDataSet.UPC.Rows[uPCDataSet.UPC.Rows.Count - 1]["UPCNumber"].ToString();//get last UPC from database
_UPCNumber = _value.Substring(0, 11);//strip out the check-digit
_UPCNumberInc = Convert.ToInt64(_UPCNumber);//convert the value to a number
for (int i = 0; i < ItemNumberList.Count; i++)
{
_UPCNumberInc = _UPCNumberInc + 1;
_UPCNumberIncrement = Convert.ToString(_UPCNumberInc);//assign the incremented value to a new variable
ItemNumberList.Add(new Codes("", _UPCNumberIncrement, "", "", ""));//**here I get the OutOfMemoreyException**
}
for (int i = 0; i < ItemNumberList.Count; i++)
{
long chkDigitOdd;
long chkDigitEven;
long chkDigitSubtotal;
chkDigitOdd = Convert.ToInt64(_UPCNumberIncrement.Substring(0, 1)) + Convert.ToInt64(_UPCNumberIncrement.Substring(2, 1)) + Convert.ToInt64(_UPCNumberIncrement.Substring(4, 1)) + Convert.ToInt64(_UPCNumberIncrement.Substring(6, 1)) + Convert.ToInt64(_UPCNumberIncrement.Substring(8, 1)) + Convert.ToInt64(_UPCNumberIncrement.Substring(10, 1));
chkDigitOdd = (3 * chkDigitOdd);
chkDigitEven = Convert.ToInt64(_UPCNumberIncrement.Substring(1, 1)) + Convert.ToInt64(_UPCNumberIncrement.Substring(3, 1)) + Convert.ToInt64(_UPCNumberIncrement.Substring(5, 1)) + Convert.ToInt64(_UPCNumberIncrement.Substring(7, 1)) + Convert.ToInt64(_UPCNumberIncrement.Substring(9, 1));
chkDigitSubtotal = (300 - (chkDigitEven + chkDigitOdd));
_chkDigit = chkDigitSubtotal.ToString();
_chkDigit = _chkDigit.Substring(_chkDigit.Length - 1, 1);
ItemNumberList.Add(new Codes("", "",_chkDigit, "", ""));
}
Est-ce la bonne façon de procéder, en utilisant une liste, ou devrais-je envisager une manière différente?
Je développerai mon commentaire:
... si vous êtes ajout ou suppression éléments, vous voulez une liste (ou une autre structure de données flexible). Les tableaux ne sont vraiment bons que lorsque vous savez exactement de combien d'éléments vous avez besoin au début.
Tableaux sont bons lorsque vous avez un nombre fixe d'éléments qui est peu susceptible de changer et que vous souhaitez y accéder de manière non séquentielle.
Listes liées sont optimisés pour des ajouts et des suppressions rapides à chaque extrémité, mais sont lents à accéder au milieu.
Listes de tableaux (comme List<T>
en C #!) sont un mélange des deux, avec des ajouts assez rapides et accès aléatoire. List<T>
sera souvent votre collection préférée lorsque vous ne savez pas quoi utiliser.
La plupart des langages modélisent les tableaux sous forme de données contiguës en mémoire, dont chaque élément a la même taille. Disons que nous avions un tableau de int
s (affiché comme [adresse: valeur], en utilisant des adresses décimales parce que je suis paresseux)
[0: 10][32: 20][64: 30][96: 40][128: 50][160: 60]
Chacun de ces éléments est un entier 32 bits, nous savons donc combien d'espace il prend en mémoire (32 bits!). Et nous connaissons l'adresse mémoire du pointeur vers le premier élément.
Il est très facile d'obtenir la valeur de tout autre élément de ce tableau:
Disons que notre premier élément est à '0'. Nous savons que notre deuxième élément est à '32' (0 + (32 * 1)), et notre troisième élément est à 64 (0 + (32 * 2)).
Le fait que nous puissions stocker toutes ces valeurs côte à côte en mémoire signifie que notre tableau est aussi compact que possible. Cela signifie également que tous nos éléments doivent rester ensemble pour que les choses continuent à fonctionner!
Dès que nous ajoutons ou supprimons un élément, nous devons récupérer tout le reste et les copier dans un nouvel emplacement en mémoire, pour nous assurer qu'il n'y a pas d'espace entre les éléments et que tout a assez de place. Cela peut être très lent, surtout si vous le faites chaque fois que vous souhaitez ajouter un seul élément.
Contrairement aux tableaux, les listes liées n'ont pas besoin que tous leurs éléments soient côte à côte en mémoire. Ils sont composés de nœuds, qui stockent les informations suivantes:
Node<T> {
Value : T // Value of this element in the list
Next : Node<T> // Reference to the node that comes next
}
La liste elle-même conserve une référence à head et tail (premier et dernier noeuds) dans la plupart des cas, et garde parfois une trace de sa taille.
Si vous voulez ajouter un élément à la fin de la liste, tout ce que vous avez à faire est d'obtenir le tail, et changer son Next
pour référencer un nouveau Node
contenant votre valeur. La suppression de la fin est également simple - il suffit de déréférencer la valeur Next
du nœud précédent.
Malheureusement, si vous avez un LinkedList<T>
avec 1000 éléments, et vous voulez l'élément 500, il n'y a pas de moyen facile de passer directement au 500e élément comme il en existe avec un tableau. Vous devez commencer à head, et continuer à aller au nœud Next
, jusqu'à ce que vous l'ayez fait 500 fois.
C'est pourquoi l'ajout et la suppression d'un LinkedList<T>
est rapide (lorsque vous travaillez aux extrémités), mais l'accès au milieu est lent.
Edit: Brian souligne dans les commentaires que les listes liées ont un risque de provoquer une erreur de page, car elles ne sont pas stockées dans la mémoire contiguë. Cela peut être difficile à évaluer et peut rendre les listes liées encore plus lentes que vous ne le pensez, étant donné leur complexité temporelle.
List<T>
compromis pour les deux T[]
et LinkedList<T>
et propose une solution raisonnablement rapide et facile à utiliser dans la plupart des situations.
En interne, List<T>
est un tableau! Il doit encore sauter à travers les cerceaux de la copie de ses éléments lors du redimensionnement, mais il tire quelques astuces intéressantes.
Pour commencer, l'ajout d'un seul élément ne provoque généralement pas la copie du tableau. List<T>
s'assure qu'il y a toujours assez de place pour plus d'éléments. Lorsqu'il s'épuise, au lieu d'allouer un nouveau tableau interne avec juste un nouvel élément, il allouera un nouveau tableau avec plusieurs nouveaux éléments (souvent deux fois beaucoup comme il détient actuellement!).
Les opérations de copie sont coûteuses, donc List<T>
les réduit autant que possible, tout en permettant un accès aléatoire rapide. En tant qu'effet secondaire, cela peut finir par perdre un peu plus d'espace qu'un tableau droit ou une liste liée, mais cela vaut généralement le compromis.
Utilisation List<T>
. C'est normalement ce que vous voulez, et cela semble être correct pour vous dans cette situation (où vous appelez .Add ()). Si vous n'êtes pas sûr de ce dont vous avez besoin, List<T>
est un bon point de départ.
Les tableaux sont bons pour les choses hautes performances, "Je sais que j'ai besoin exactement d'éléments X". Alternativement, ils sont utiles pour des structures rapides et uniques "J'ai besoin de regrouper ces X choses que j'ai déjà définies ensemble afin que je puisse les parcourir".
Il existe un certain nombre d'autres classes de collection. Stack<T>
est comme une liste chaînée qui ne fonctionne que par le haut. Queue<T>
fonctionne comme une liste premier entré, premier sorti. Dictionary<T, U>
est un mappage associatif non ordonné entre les clés et les valeurs. Jouez avec eux et apprenez à connaître les forces et les faiblesses de chacun. Ils peuvent faire ou défaire vos algorithmes.
Alors que réponse KChaloux est génial, je voudrais souligner une autre considération: List<T>
Est beaucoup plus puissant qu'un tableau. Les méthodes de List<T>
Sont très utiles dans de nombreuses circonstances - un tableau n'a pas ces méthodes et vous pouvez passer beaucoup de temps à implémenter des solutions de contournement.
Donc, du point de vue du développement, j'utilise presque toujours List<T>
Parce que lorsqu'il y a des exigences supplémentaires, elles sont souvent beaucoup plus faciles à implémenter lorsque vous utilisez un List<T>
.
Cela conduit à un dernier problème: mon code (je ne connais pas le vôtre) contient 90% List<T>
, Donc les tableaux ne conviennent pas vraiment. Quand je les passe, je dois appeler leur fonction .toList()
méthode et les convertir en une liste - c'est ennuyeux et si lent que tout gain de performances lié à l'utilisation d'un tableau est perdu.
Personne n'a cependant mentionné cette partie: "Et ici, je reçois déjà une exception de mémoire insuffisante." Ce qui est entièrement dû à
for (int i = 0; i < ItemNumberList.Count; i++)
{
ItemNumberList.Add(new item());
}
Il est clair de voir pourquoi. Je ne sais pas si vous vouliez ajouter à une autre liste ou si vous devez simplement stocker ItemNumberList.Count
en tant que variable avant la boucle pour obtenir le résultat souhaité, mais cela est tout simplement cassé.
Programmers.SE est pour "... intéressé par les questions conceptuelles sur le développement de logiciels ...", et les autres réponses l'ont traité comme tel. Essayez http://codereview.stackexchange.com à la place, là où cette question conviendrait. Mais même là, c'est horrible, car nous ne pouvons que supposer que ce code commence à _Click
, qui n'a pas d'appel à multiValue1
où vous dites que l'erreur se produit.