user1073472
user1073472

Reputation: 139

C# Adding an array or list into an List

I've got a List of Document

public class Document
{
    public string[] fullFilePath;
    public bool isPatch;
    public string destPath;


    public Document() { }

    public Document(string[] fullFilePath, bool isPatch, string destPath)
    {
        this.fullFilePath = fullFilePath;
        this.isPatch = isPatch;
        this.destPath = destPath;
    }

The fullFilepath should a List or an Array of Paths.

For example:

Document 1
 ---> C:\1.pdf
 ---> C:\2.pdf

Document 2
 ---> C:\1.pdf
 ---> C:\2.pdf
 ---> C:\3.pdf

etc.

My problem if I am using an array string all Documents got "null" in its fullFilePath. If I'm using a List for the fullFilePath all Documents got the same entries from the last Document.

Here is how the List is filled:

            int docCount = -1;
            int i = 0;


            List<Document> Documents = new List<Document>();
            string[] sourceFiles = new string[1];

            foreach (string file in filesCollected)
            {
                string bc;
                string bcValue;


                if (Settings.Default.barcodeEngine == "Leadtools")
                {
                    bc = BarcodeReader.ReadBarcodeSymbology(file);
                    bcValue = "PatchCode";
                }
                else
                {
                    bc = BarcodeReader.ReadBacrodes(file);
                    bcValue = "009";
                }
                if (bc == bcValue)
                {
                    if(Documents.Count > 0)
                    {
                         Array.Clear(sourceFiles, 0, sourceFiles.Length);
                         Array.Resize<string>(ref sourceFiles, 1);
                         i = 0;
                    }
                    sourceFiles[i] =  file ;
                    i++;
                    Array.Resize<string>(ref sourceFiles, i + 1);

                    Documents.Add(new Document(sourceFiles, true,""));
                    docCount++;


                }
                else
                {
                    if (Documents.Count > 0)
                    {
                        sourceFiles[i] = file;
                        i++;
                        Array.Resize<string>(ref sourceFiles, i + 1);

                        Documents[docCount].fullFilePath = sourceFiles;
                    }
                }                
            }

Upvotes: 1

Views: 170

Answers (2)

Steve
Steve

Reputation: 216293

You are using the same instance of the array for every document. The instance is updated with a new list of files at every inner loop, but an array is a reference to an area of memory (oversimplification, I know but for the purpose of this answer is enough) and if you change the content of that area of memory you are changing it for every document.

You need to create a new instance of the source files for every new document you add to your documents list. Moreover, when you are not certain of the number of elements that you want to be included in the array, it is a lot better to use a generic List and remove all that code that handles the resizing of the array.

First change the class definition

public class Document
{
    public List<string> fullFilePath;
    public bool isPatch;
    public string destPath;


    public Document() { }

    public Document(List<string> fullFilePath, bool isPatch, string destPath)
    {
        this.fullFilePath = fullFilePath;
        this.isPatch = isPatch;
        this.destPath = destPath;
    }
}

And now change your inner loop to

foreach (string file in filesCollected)
{
    string bc;
    string bcValue;
    ....
    if (bc == bcValue)
    {
        List<string> files = new List<string>();
        files.Add(file);
        Documents.Add(new Document(files, true, ""));
        docCount++;
    }
    else
        Documents[docCount].fullFilePath.Add(file);
}

Notice that when you need to add a new Document I build a new List<string>, add the current file and pass everything at the constructor (In reality this should be moved directly inside the constructor of the Document class). When you want to add just a new file you could add it directly to the public fullFilePath property

Moving the handling of the files inside the Documents class could be rewritten as

public class Document
{
    public List<string> fullFilePath;
    public bool isPatch;
    public string destPath;

    public Document() 
    {
         // Every constructory initializes internally the List
         fullFilePath = new List<string>(); 
    }

    public Document(string aFile, bool isPatch, string destPath)
    {
        // Every constructory initializes internally the List
        fullFilePath = new List<string>(); 
        this.fullFilePath.Add(aFile);
        this.isPatch = isPatch;
        this.destPath = destPath;
    }
    public void AddFile(string aFile)
    {
        this.fullFilePath.Add(aFile);
    }
}

Of course, now in you calling code you pass only the new file or call AddFile without the need to check for the list initialization.

Upvotes: 2

erikscandola
erikscandola

Reputation: 2936

The issue should be here:

string[] sourceFiles = new string[1];

If you move this line of code in your foreach you should solve this problem because in your foreach you always use the same variable, so the same reference.

int docCount = -1;
int i = 0;

List<Document> Documents = new List<Document>();

foreach (string file in filesCollected)
{
    string[] sourceFiles = new string[1];
    string bc;
    string bcValue;

    if (Settings.Default.barcodeEngine == "Leadtools")
    {
        bc = BarcodeReader.ReadBarcodeSymbology(file);
        bcValue = "PatchCode";
    }
    else
    {
        bc = BarcodeReader.ReadBacrodes(file);
        bcValue = "009";
    }
    if (bc == bcValue)
    {
        if(Documents.Count > 0)
        {
            Array.Clear(sourceFiles, 0, sourceFiles.Length);
            Array.Resize<string>(ref sourceFiles, 1);
            i = 0;
        }
        sourceFiles[i] =  file ;
        i++;
        Array.Resize<string>(ref sourceFiles, i + 1);

        Documents.Add(new Document(sourceFiles, true,""));
        docCount++;
    }
    else
    {
        if (Documents.Count > 0)
        {
            sourceFiles[i] = file;
            i++;
            Array.Resize<string>(ref sourceFiles, i + 1);

            Documents[docCount].fullFilePath = sourceFiles;
        }
    }                
}

Upvotes: 1

Related Questions