Alternative for System.Collections.Generic.List, to reduce build size.

Hello,
I just finished, built and uploaded my game to the Google Play Store and I just noticed that the build size is quite big considering it’s actual functionality. All the game does is show you some text and some icons and then change the text and icons when you tap. The text and the icons come from a list.

I read that you can reduce the size of your build by avoiding System.dll, but in order to use the list I need System.generics. So I am looking for an alternative to the list so that I can reduce the size of mye build.
Also any other tips on how to reduce the size of the game is very welcome.

Here is my editor log, showing what makes up the size of the build, as well as the dlls I’m using.

Textures      235.2 kb	 4.7% 
Meshes        0.0 kb	 0.0% 
Animations    0.0 kb	 0.0% 
Sounds        0.0 kb	 0.0% 
Shaders       175.5 kb	 3.5% 
Other Assets  45.9 kb	 0.9% 
Levels        7.3 kb	 0.1% 
Scripts       482.5 kb	 9.7% 
Included DLLs 3.9 mb	 80.8% 
File headers  8.5 kb	 0.2% 
Complete size 4.9 mb	 100.0% 

Mono dependencies included in the build
Dependency assembly - Mono.Security.dll
Dependency assembly - System.Core.dll
Dependency assembly - System.dll
Dependency assembly - mscorlib.dll
Dependency assembly - UnityEngine.Advertisements.dll
Dependency assembly - UnityEngine.UI.dll
Dependency assembly - UnityEngine.Networking.dll
Dependency assembly - Assembly-CSharp.dll

As you can see, dlls take up more than 75% of the size, which is inconvenient.

Here’s how I use the List

using UnityEngine;
using System.Collections.Generic;

public class ListOfStatements : MonoBehaviour {

    List<Statement> statements;
    public List<Statement> shuffledList;

	// Use this for initialization
	void Awake () {
        statements = new List<Statement>();
        shuffledList = new List<Statement>();

        FillList();

        for (int i = 0; i < statements.Count;)
        {
            int r = Random.Range(0, statements.Count);

            shuffledList.Add(statements[r]);
            statements.Remove(statements[r]);
        }

        foreach (Statement s in shuffledList)
        {
            Debug.Log(s.text + " " + s.drinks + " " + s.category);
        }



    }
	
	// Update is called once per frame
	void FillList ()
    {
        statements.Add(new Statement("Vært vikar", 1, 1));
        statements.Add(new Statement("Vært barnevakt", 2, 1));
        statements.Add(new Statement("Bygd trehytte", 1, 1));
        statements.Add(new Statement("Gravd en snøhule", 1, 1));

These are just 4 of the 300 or so statements in my List.

This is a Statement

public class Statement
{
    public string text;
    public int drinks;
    public int category;

    public Statement(string _text, int _drinks, int _category)
    {
        text = _text;
        drinks = _drinks;
        category = _category;
    }
}

Aaand here’s how I change the statements

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Advertisements;

public class StatementManager : MonoBehaviour {

    public Text currentStatement;

    public GameObject oneDrink, threeDrink, fiveDrink, oneShot;

    GameObject currentDrink;
    ListOfStatements listOfStatements;
    int listIndex = 0;
    public bool ranOnce = false;
    int adIndex = 15;

    void Awake()
    {
        listOfStatements = GetComponent<ListOfStatements>();
        
    }

    void Start()
    {
        currentStatement.text = listOfStatements.shuffledList[0].text;
        ChangeIcon();
    }

    public void ChangeText()
    {
        if (!ranOnce)
        {
            if (listIndex == adIndex)
            {
                adIndex += 15;
                //ShowDefaultAd();
            }

            ranOnce = true;
            listIndex++;
            Destroy(currentDrink);
            currentStatement.text = listOfStatements.shuffledList[listIndex].text;
            ChangeIcon();
            

        }
        if (listIndex == listOfStatements.shuffledList.Count-1)
        {
            listIndex = 0;
        }
    }

    void ChangeIcon()
    {
        switch (listOfStatements.shuffledList[listIndex].drinks)
        {
            case 1:
                currentDrink = Instantiate(oneDrink);
                break;
            case 2:
                currentDrink = Instantiate(threeDrink);
                break;
            case 3:
                currentDrink = Instantiate(fiveDrink);
                break;
            case 4:
                currentDrink = Instantiate(oneShot);
                break;
        }
    }



using UnityEngine;

public class TouchManager : MonoBehaviour
{
    StatementManager statementManager;

    void Awake()
    {
        statementManager = GetComponent<StatementManager>();
    }

    void Update()
    {
        if (Input.touchCount > 0)
        {
            statementManager.ChangeText();
        }
        if (Input.touchCount < 1)
        {
            statementManager.ranOnce = false;
        }
    }
}

Basicly, every Statement has a String and an int that decides what Text to show and which icon to show with it. The Statement has an int Category as well, which is not used in this build, but is in there for integrating a new function later.

I need a list or an array to hold these Statements and let me sequentially cycle through them.

Also, if you have any ideas on optimizing the shuffling of the List, I’d gladly accept.

EDIT: The following does not work, see Bunny83’s comment below.

You can just use the relevant code from the reference source, remove the Contract statements and replace the ThrowHelper statements. The following code should work, but bear in mind that this snippet only contains the functions you use in your code. However, it should be fairly simple to add other functions if needed. You also still have to use System and it probably would not be worthwhile to replace the classes from System with the reference code, but hopefully the size gets small enough without System.Collections.Generic.

using System;
public interface IEnumerator
{    
    bool MoveNext();

    System.Object Current
    {
        get;
    }
        
    void Reset();
}

public interface IEnumerator<out T> : IDisposable, IEnumerator
{
    new T Current
    {
        get;
    }
}

public class List<T>
{
    private const int _defaultCapacity = 4;

    private T[] _items;
    private int _size;
    private int _version;

    static readonly T[] _emptyArray = new T[0];


    public int Capacity
    {
        get
        {
            return _items.Length;
        }
        set
        {
            if (value < _size)
            {
                throw new ArgumentOutOfRangeException();                
            }
            
            if (value != _items.Length)
            {
                if (value > 0)
                {
                    T[] newItems = new T[value];
                    if (_size > 0)
                    {
                        Array.Copy(_items, 0, newItems, 0, _size);
                    }
                    _items = newItems;
                }
                else
                {
                    _items = _emptyArray;
                }
            }
        }
    }

    public int Count
    {
        get
        {
            return _size;
        }
    }

    public List()
    {
        _items = _emptyArray;
    }

    private void EnsureCapacity(int min)
    {
        if (_items.Length < min)
        {
            int newCapacity = _items.Length == 0 ? _defaultCapacity : _items.Length * 2;
            if ((uint)newCapacity > System.Int32.MaxValue) newCapacity = System.Int32.MaxValue;
            if (newCapacity < min) newCapacity = min;
            Capacity = newCapacity;
        }
    }

    public T this[int index]
    {
        get
        {
            if ((uint)index >= (uint)_size)
            {
                throw new ArgumentOutOfRangeException();
            }
            return _items[index];
        }

        set
        {
            if ((uint)index >= (uint)_size)
            {
                throw new ArgumentOutOfRangeException();
            }
            _items[index] = value;
            _version++;
        }
    }

    public void Add(T item)
    {
        if (_size == _items.Length) EnsureCapacity(_size + 1);
        _items[_size++] = item;
        _version++;
    }

    public int IndexOf(T item)
    {
        return Array.IndexOf(_items, item, 0, _size);
    }

    public void RemoveAt(int index)
    {
        if ((uint)index >= (uint)_size)
        {
            throw new ArgumentOutOfRangeException();         
        }
        _size--;
        if (index < _size)
        {
            Array.Copy(_items, index + 1, _items, index, _size - index);
        }
        _items[_size] = default(T);
        _version++;
    }

    public bool Remove(T item)
    {
        int index = IndexOf(item);
        if (index >= 0)
        {
            RemoveAt(index);
            return true;
        }

        return false;
    }

    public Enumerator GetEnumerator()
    {
        return new Enumerator(this);
    }

    [Serializable]
    public struct Enumerator : IEnumerator<T>, IEnumerator
    {
        private List<T> list;
        private int index;
        private int version;
        private T current;

        internal Enumerator(List<T> list)
        {
            this.list = list;
            index = 0;
            version = list._version;
            current = default(T);
        }

        public void Dispose()
        {
        }

        public bool MoveNext()
        {

            List<T> localList = list;

            if (version == localList._version && ((uint)index < (uint)localList._size))
            {
                current = localList._items[index];
                index++;
                return true;
            }
            return MoveNextRare();
        }

        private bool MoveNextRare()
        {
            if (version != list._version)
            {
                throw new InvalidOperationException();
            }

            index = list._size + 1;
            current = default(T);
            return false;
        }

        public T Current
        {
            get
            {
                return current;
            }
        }

        System.Object IEnumerator.Current
        {
            get
            {
                if (index == 0 || index == list._size + 1)
                {
                    throw new InvalidOperationException();
                }
                return Current;
            }
        }

        void IEnumerator.Reset()
        {
            if (version != list._version)
            {
                throw new InvalidOperationException();
            }

            index = 0;
            current = default(T);
        }

    }
}