Why not just parse these explicitly? You have a limited number of properties, so it's not very difficult. Instead of using a constructor requiring many arguments, I used a static method that returns a new DailyValues
instance as it's return type. This is similar to DateTime.FromBinary
etc.
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
namespace CsvDemo
{
class Program
{
static void Main(string[] args)
{
List<DailyValues> values = File.ReadAllLines("C:\Users\Josh\Sample.csv")
.Skip(1)
.Select(v => DailyValues.FromCsv(v))
.ToList();
}
}
class DailyValues
{
DateTime Date;
decimal Open;
decimal High;
decimal Low;
decimal Close;
decimal Volume;
decimal AdjClose;
public static DailyValues FromCsv(string csvLine)
{
string[] values = csvLine.Split(',');
DailyValues dailyValues = new DailyValues();
dailyValues.Date = Convert.ToDateTime(values[0]);
dailyValues.Open = Convert.ToDecimal(values[1]);
dailyValues.High = Convert.ToDecimal(values[2]);
dailyValues.Low = Convert.ToDecimal(values[3]);
dailyValues.Close = Convert.ToDecimal(values[4]);
dailyValues.Volume = Convert.ToDecimal(values[5]);
dailyValues.AdjClose = Convert.ToDecimal(values[6]);
return dailyValues;
}
}
}
Of course, you can still add a default constructor, and you will want to add exception handling in case the parsing fails (you can also use TryParse
for that).
- The
File.ReadAllLines
reads all lines from the CSV file into a string array.
- The
.Skip(1)
skips the header line.
- The
.Select(v => DailyValues.FromCsv(v))
uses Linq to select each line and create a new DailyValues
instance using the FromCsv
method. This creates a System.Collections.Generic.IEnumerable<CsvDemo.DailyValues>
type.
- Finally, the
.ToList()
convers the IEnumerable
to a List
to match the type you want.
Instead of using Linq you could have simply used a foreach
loop to add each DailyValues
instance to your list.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…