How to mention List<T> size before two element join

T.Zacks 3,996 Reputation points
2021-04-08T18:59:13.823+00:00

See how my code. where i am joining two datatable and stored the result set into List<T>

List<QCHelper> BogeyConfigList = null;
BogeyConfigList = (from bogyconfiglist in Bogeylist.AsEnumerable().AsParallel() 
join LiList in list.AsEnumerable().AsParallel()             
on new
{
    val = bogyconfiglist.LineItem.Trim().ToUpper(),
    val1 = bogyconfiglist.Section.Trim().ToUpper()
}
equals new
{
    val = LiList.LI.Trim().ToUpper(),
    val1 = LiList.Section.Trim().ToUpper()
}
into conbogylist
from confg in conbogylist.DefaultIfEmpty()
select new QCHelper()
{
    Section = bogyconfiglist.Section,
    Li = bogyconfiglist.LineItem,
    CrossCalc1Q = confg == null ? string.Empty : (confg.CrossCalc1Q == null ? "" : confg.CrossCalc1Q.Replace("~9999", string.Empty).Trim()),
    CrossCalc2Q = confg == null ? string.Empty : (confg.CrossCalc2Q == null ? "" : confg.CrossCalc2Q.Replace("~9999", string.Empty).Trim()),
    CrossCalc3Q = confg == null ? string.Empty : (confg.CrossCalc3Q == null ? "" : confg.CrossCalc3Q.Replace("~9999", string.Empty).Trim()),
    CrossCalc4Q = confg == null ? string.Empty : (confg.CrossCalc4Q == null ? "" : confg.CrossCalc4Q.Replace("~9999", string.Empty).Trim()),
    CrossCalcFY = confg == null ? string.Empty : (confg.CrossCalcFY == null ? "" : confg.CrossCalcFY.Replace("~9999", string.Empty).Trim()),
    AllowComma = confg == null ? false : confg.AllowComma,
    AllowedDecimalPlace = confg == null ? string.Empty : confg.AllowedDecimalPlace,
    AllowPercentageSign = confg == null ? false : confg.AllowPercentageSign,
    CurrencySign = confg == null ? string.Empty : confg.CurrencySign,
    IsQcCheck = confg == null ? false : confg.QCCheck,
    QcType = confg == null ? string.Empty : confg.QCType,
    FormulaLiConfig = confg == null ? string.Empty : (confg.StandrdFormula == null ? "" : confg.StandrdFormula.Replace("~9999", string.Empty).Trim()),
    xFundCode = bogyconfiglist.xFundCode == null ? string.Empty : bogyconfiglist.xFundCode
}).Distinct().ToList<QCHelper>();

resultset stored into BogeyConfigList but i heard that List will have many empty items in it when data will be stored there and those empty item will consume memory.

so before join how could i declare List<T> with proper size as a result join result set can accommodate into List<T> ?

Please guide me how to handle this situation. i have like series of many joins in my routine where i am not able to mention List<T> size because i do not in advance how many data will be there after join in result set. discuss best approach to handle my scenario where i can save some memory. thanks

Developer technologies | C#
0 comments No comments
{count} votes

Accepted answer
  1. Viorel 122.9K Reputation points
    2021-04-09T08:00:45.367+00:00

    The list is created by ToList based on available elements, which are returned by Distinct, therefore no huge extra allocation is expected, which sometimes appears in case of other operations with lists.

    In order to minimise the unused memory, you can execute BogeyConfigList.TrimExcess() at the end.


2 additional answers

Sort by: Most helpful
  1. Karen Payne MVP 35,586 Reputation points Volunteer Moderator
    2021-04-08T19:10:08.363+00:00

    This is an extremely simple example done on string but can be any type done here in a unit test method.

    Example 1

    [TestMethod]  
    public void LimitListToSize()  
    {  
        int maxElements = 2;  
        var list = new List<string>();  
        list.Capacity = maxElements;  
      
        while (list.Count <= maxElements -1)  
        {  
            list.Add("X");  
        }  
      
        Assert.AreEqual(list.Count, maxElements);  
          
    }  
    

    Example 2

    Uses the following class. And the following container

    public class Person  
    {  
        public int Id { get; set; }  
        public string FirstName { get; set; }  
        public string LastName { get; set; }  
    }  
    

    Unit test

    [TestMethod]  
    public void LimitedPeople()  
    {  
        // arrange  
        int maxItems = 3;  
          
        var people = new List<Person>  
        {  
            new Person() {Id = 1, FirstName = "Karen", LastName = "Payne"},  
            new Person() {Id = 2, FirstName = "Jim", LastName = "Gallagher"},  
            new Person() {Id = 3, FirstName = "Anne", LastName = "Smith"},  
            new Person() {Id = 4, FirstName = "Bob", LastName = "Lebow"},  
            new Person() {Id = 5, FirstName = "Zack", LastName = "Anderson"}  
        };  
      
        // act  
        LimitedList<Person> limitedList = new LimitedList<Person>(maxItems);  
        foreach (var person in people)  
        {  
            limitedList.Add(person);  
        }  
      
          
        List<Person> results = limitedList.ToList();  
          
        // assert  
        Assert.IsTrue(results.Count == maxItems);  
    }  
    

    85889-figure1.png

    1 person found this answer helpful.
    0 comments No comments

  2. Timon Yang-MSFT 9,606 Reputation points
    2021-04-09T02:29:04.557+00:00

    declare List<T> with proper size

    I'm afraid this won't work.

    Although List is using arrays as backing storage, the expansion mechanism of List causes its size to change according to actual conditions.

    EnsureCapacity method in the source code of List:

            // Ensures that the capacity of this list is at least the given minimum  
            // value. If the currect capacity of the list is less than min, the  
            // capacity is increased to twice the current capacity or to min,  
            // whichever is larger.  
            private void EnsureCapacity(int min) {  
                if (_items.Length < min) {  
                    int newCapacity = _items.Length == 0? _defaultCapacity : _items.Length * 2;  
                    // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow.  
                    // Note that this check works even when _items.Length overflowed thanks to the (uint) cast  
                    if ((uint)newCapacity > Array.MaxArrayLength) newCapacity = Array.MaxArrayLength;  
                    if (newCapacity < min) newCapacity = min;  
                    Capacity = newCapacity;  
                }  
            }  
    

    If you are only worried about possible empty items, you may consider processing the empty values after getting the results, like this:

     var re = strs.Where(s => !string.IsNullOrWhiteSpace(s)).ToList();  
    

    A post for your reference: how to remove empty strings from list, then remove duplicate values from a list


    If the response is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.