//!!!This seems too specific. Better would be one that returns RowKeyColKeyValue from a file and then that could be changed to string[] outside this class.
        internal static IEnumerable <string[]> EachSparseLine(string filePattern,
                                                              StaticStringToStoreListDelegate staticStringiToStoreListDelegate,
                                                              Converter <TStore, string> StoreToSparseValueDelegate,
                                                              bool zeroIsOK, string fileMessageOrNull, TStore storeMissingValue, CounterWithMessages counterWithMessages)
        {
            foreach (string fileName in FileUtils.GetFiles(filePattern, zeroIsOK))
            {
                if (null != fileMessageOrNull)
                {
                    Console.WriteLine(fileMessageOrNull, fileName);
                }

                using (TextReader textReader = FileUtils.OpenTextStripComments(fileName))
                {
                    string header = textReader.ReadLine();
                    SerialNumbers <string> colSerialNumberCollection = ColSerialNumbersFromHeader(header, fileName);

                    string line;
                    while (null != (line = textReader.ReadLine()))
                    {
                        var           rowKeyAndStructList = CreateRowKeyAndStructList(line, filePattern, colSerialNumberCollection.Count, staticStringiToStoreListDelegate, counterWithMessages);
                        string        rowKey     = rowKeyAndStructList.Key;
                        List <TStore> structList = rowKeyAndStructList.Value;
                        for (int colIndex = 0; colIndex < colSerialNumberCollection.Count; ++colIndex)
                        {
                            TStore store = structList[colIndex];
                            if (!store.Equals(storeMissingValue)) //OK to use Equals because TStore can't be null
                            {
                                string   val         = StoreToSparseValueDelegate(store);
                                string[] stringArray = new string[] { rowKey, colSerialNumberCollection.GetItem(colIndex), val };
                                yield return(stringArray);
                            }
                        }
                    }
                }
            }
        }
        static private KeyValuePair <string, List <TStore> > CreateRowKeyAndStructList(string line, string denseStructFileName,
                                                                                       int colCount, StaticStringToStoreListDelegate stringToStoreListDelegate,
                                                                                       CounterWithMessages counterWithMessages)
        {
            counterWithMessages.Increment();
            string valueString;
            string rowKey = SplitVarLine(line, denseStructFileName, colCount, out valueString);

            List <TStore> structList = stringToStoreListDelegate(valueString, colCount);

            if (structList.Count != colCount)
            {
                throw new MatrixFormatException("Every data string should have a value per col. " + rowKey);
            }
            return(new KeyValuePair <string, List <TStore> >(rowKey, structList));
        }