Есть ли способ использовать один класс, который работает с массивом с двумя записями различной структуры? - PullRequest
1 голос
/ 10 мая 2019

Я хочу прочитать входной файл и сохранить входящие данные в массив структур, используя методы класса из ListClass. Что я и сделал. Затем я хочу прочитать из отдельного файла, формат которого отличается от первого, в отдельный массив, но с использованием того же ListClass. Возможно ли это?

Я пытался использовать абстрактный класс, но, похоже, не совсем правильно понял. для небольшого примера:

 class ListClass 
 {           
     public struct struct1
     {
         public string strPart;
         public string strDescrip;
         public int intQty;
     }  

     public struct struct2
     {
         public string strPart;
         public char chrSold;
         public int intQtySold;
     }

     public int MAX_ELEMENTS = 4;

     //PRIVATE DATA MEMBERS
     private arr[] listArr;
     private int length;
     private int currPos;

     public ListClass()
     {
         length = 0;
         currPos = 0;
         listArr = new arr[MAX_ELEMENTS];
     }


     public ListClass(int size)
     {
         listArr = new Array[size];
     }


    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


    //Purpose:  Create a deep copy of the list
    //Pre:      List has been instantiated and orig contains list to be copied
    //Post:     An identical, deep copy of the list has been created.
    public ListClass(/*in*/ ListClass orig) //list to be copied
    {
        length = orig.length;
        //currPos = orig.currPos;

        // Allocate the new list
        listArr = new Array[MAX_ELEMENTS];

        // Copy over all the values
        for (int i = 0; i < MAX_ELEMENTS; i++)
            listArr[i] = orig.listArr[i];
    }//end copy constructor


    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


    //Purpose:  Indicates whether or not the list is empty
    //Pre:      List has been instantiated
    //Post:     Returns true if list is empty and false, otherwise
    public bool IsEmpty()
    {
        return (length == 0);
    }//end IsEmpty


    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


    //Purpose:  Indicates whether or not the list is full
    //Pre:      List has been instantiated
    //Post:     Returns true if list is full and false, otherwise
    public bool IsFull()
    {
        return false;
    } //end IsFull


    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


    //Purpose:  Inserts item into the list
    //Pre:      List is not full
    //Post:     Item has been inserted at the end of the current list, length has 
    //          been modified 
    //Error Handling:
    //          if the key already exists within list, do not insert newItem and return false 
    //          if the list is full, do not insert the item and return false

    public void Insert(/*in*/ Array newItem)        //item to be added
    {
        // Make sure there is space
        if (NeedToExpand())
            //Expand if needed and insert new item
            Expand();

        listArr[length] = newItem;
        length++;
    } //end Insert


    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


    //Purpose:  Deletes an item from the list
    //Pre:      Method Find has been called to find the item to delete, and the 
    //          that item is in the list.CurrPos now points at the item to be deleted
    //Post:     The item denoted by currPos has been deleted from the list, lemgth has
    //          been updated.
    //Error Handling: If the list is empty, no changes are made
    public void Delete(string key)
    {
        if (IsEmpty())
            Console.WriteLine("List is Empty");
        else
        {
            if(!Find(key))
                Console.WriteLine("Item not Found");
            else
            {
                if (length > 0)
                {
                    for (int i = currPos; i < length; i++)
                        listArr[i] = listArr[i + 1];

                    length--;
                }

                if (NeedToShrink())
                    Contract();
            }
        }
    }//end Delete


    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


    //Purpose:  Moves to the beginning of the list
    //Pre:      List has been instantiated
    //Post:     currPos has been set to the first position in the list
    public void FirstPosition()
    {
        currPos = 0;
    }//end FirstPosition


    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


    //Purpose:  Moves to the next element in the list
    //Pre:      List has been instantiated
    //Post:     currPos has been moved to the next position in the list
    //Error Handling: if currPos is already at the end of the list, currPos is not modified
    public void NextPosition()
    {
        if (!EndOfList())
            currPos++;
        else
            Console.WriteLine("End of List");
    } //end NextPosition


    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


    //Purpose:  Determines if currPos is at the end of the list
    //Pre:      List has been instantiated
    //Post:     Returns true if currPos is at the end of the list, and false, otherwise
    //          end-of-list denotes the first empty index in the list.

    public bool EndOfList()
    {
        return (currPos == length - 1);
    }//end EndOfList


    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~        


    //Purpose:  Determines whether or not item is in the list
    //Pre:      item is assigned a value
    //Post:     If item is in the list then true is returned  and currPos contains
    //                the index of the item in the list, otherwise, 
    //                false is returned and currPos is at zero.
    public bool Find(/*in*/ string key)     // item to be found
    {
        bool found = false;
        currPos = 0;

        while (!found && currPos < length)
        {
            if (listArr[currPos] == key)
                found = true;
            else
                currPos++;
        }// End while

        if (!found)
            currPos = 0;

        return found;
    }//end Find


    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


    //Purpose:  Returns the current item in the list(denoted by currPos)
    //Pre:      List is not Empty
    //Post:     Returns the item at currPos
    //Error Handling: if Retrieve is called on an empty list an InvRec with a key set 
    //                  to int.MinValue is returned. 
    public object Retrieve()
    {
        object inv = new object();

        if (!IsEmpty())
            return listArr[currPos];
        else
        {
            Console.WriteLine("The list is empty");
            return inv;
        }

    }//end Retrieve


    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


    //Purpose: Clears the list
    //Pre: List has been instantiated
    //Post: List has been restored to its initial condition
    public void Clear()
    {
        currPos = 0;
        length = 0;
    }//end Clear

    //Purpose: indicates if the list needs to be expanded
    //Pre: insert must be called with a new item to insert
    //Post: returns true if length equals MAX_ELEMENTS, false otherwise
    private bool NeedToExpand()
    {
        if (length == MAX_ELEMENTS)
            return true;
        else
            return false;
    }

    //Purpose: indicates if the list needs to be shrunk
    //Pre: delete must be called with a item to delete
    //Post: returns true if length is 25% of MAX_ELEMENTS, false otherwise
    private bool NeedToShrink()
    {
        if ((float)MAX_ELEMENTS * 0.25f == length)
            return true;
        else
            return false;

    }

    //Purpose: to expand the space of the list
    //Pre: NeedToExpand must return true
    //Post: the size of the list is doubled
    private void Expand()
    {
        MAX_ELEMENTS *= 2;

        ListClass tempList = new ListClass(MAX_ELEMENTS);

        for (int i = 0; i < length; i++)
            tempList.listArr[i] = listArr[i];

        listArr = tempList.listArr;
    }

    //Purpose: to contract the size of the list
    //Pre: NeedToContract must return true
    //Post: the size of the list is shrunk
    private void Contract()
    {
        if(MAX_ELEMENTS != 4)
        {
            MAX_ELEMENTS /= 2;

            ListClass tempList = new ListClass(MAX_ELEMENTS);

            for (int i = 0; i < length; i++)
                tempList.listArr[i] = listArr[i];

            listArr = tempList.listArr;
        }            
    }

Если фрагмент кода имеет какой-либо смысл. У меня есть две по-разному отформатированные структуры. Это я хотел бы сохранить в массивах с использованием всех методов в ListClass на каждом.

Ответы [ 2 ]

0 голосов
/ 13 мая 2019

Отвечая на ваш комментарий, опять же, я бы не советовал продвигать код ListClass.Вам было бы намного лучше использовать списки, встроенные в c #.

С другой стороны, если вы действительно намерены сделать это трудным путем (то есть, вероятно, неправильным путем), то кто я, чтобы остановитьты?

Два наиболее сложных способа сделать это - либо (а) объявить структуру, которая может содержать InventoryAmount или SoldAmount, либо (б) объявить массив как объект [] и использовать бокс c #.Оба подхода, скорее всего, бессмысленны с деловой точки зрения и также неэффективны.

Для первого подхода (a) просто объявите объединенную структуру, например, как это:

public struct InventoryAmountOrSoldAmount 
{
    public InventoryAmountOrSoldAmount( InventoryAmount ia => this.InventoryAmount = ia;
    public InventoryAmountOrSoldAmount( SoldAmount sa => this.SoldAmount = sa;
   public InventoryAmount { get;}
   public SoldAmount { get;}
}

Затем просто используйте это как тип вашего массива:

private InventoryAmountOrSoldAmount[] listArr = new InventoryAmountOrSoldAmount[MAXELEMENTS];

Или вторым подходом (b) было бы объявить массив следующим образом:

private object[] listArr = new object[MAXELEMENTS];

Затем вы можете назначить каждому элементу массива либо InventoryAmount, либо SoldAmount.C # упакует структуру, поместив копию в кучу и поместив указатель на нее в элементе массива.

0 голосов
/ 10 мая 2019

ОК, хорошо ... учитывая, что этот пост помечен тегом C #, я бы предложил использовать подход, который является обычным для C #.

Первый комментарий: в C # встроено множество коллекций, поэтому обычно никто не пытается писать их заново. Другой момент, типы Struct1 и Struct2 различны, и может показаться, что они имеют разные значения - мы могли бы переименовать их, возможно, в InventoryAmount и SoldAmount.

Так что вам просто нужно объявить два списка в вашем основном классе, как это

using System.Collections.Generic;
...
List<InventoryAmount> InventoryAmounts { get; } = new List<InventoryAmount>();
List<SoldAmount> SoldAmounts { get; } = new List<SoldAmount>();

Затем вы читаете в своих массивах и просто добавляете их в списки следующим образом:

InventoryAmount[] inventoryAmounts = ...
this.InventoryAmounts.AddRange( inventoryAmounts); 

SoldAmount[] soldAmounts = …
this.SoldAmounts.AddRange( soldAmounts);

На самом деле этот подход требует небольшого дополнительного выделения памяти, поскольку массивы не используются после их добавления в список. Вы можете избежать этого, поместив каждое значение непосредственно в список по мере его чтения. Или вы можете просто оставить их в массивах.

Еще один комментарий: такие методы, как FirstPosition, NextPosition, более условно выполняются с использованием Enumerator и Enumerable. Они встроены в класс List и массивы и используются функцией foreach следующим образом:

foreach (InventoryAmount ia in this.InventoryAmounts) {
   ...
}

foreach (InventoryAmount ia in inventoryAmounts) {
   ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...