Im making a basic CSV Reader. Im sepparating the header from the contents using header
and data
.
Now, my lists contain data of the type person.:
public class person
{
public int id;
public string name;
public int age;
public person(string id, string name, string age)
{
try
{
this.id = Convert.ToInt32(id);
this.name = name;
this.age = Convert.ToInt32(age);
}
catch (FormatException e)
{
Console.WriteLine(e.Message);
}
}
public string ToString()
{
return $"{id}, {name}, {age}";
}
}
Now id like to take the type data
and make a type person
that stores the information. Right now i am trying to use IEnumerable<>
for everything since many comments here say that its better for memory management. Now, since it behaves a little different then List<T>
I'm having issue making a type that stores persons. Im having errors left and right using IEnumerable
so i couldnt be bothered to write my shitty code down.
var data = file.Skip(1).Select(p => p.Split(';'));
IEnumerable<person> listofperson;
My question is, how can i make this work using IEnumerable<>
? Or should i even care and rather go for List<>
?
CodePudding user response:
IEnumerable<T>
is just an interface, not an implementation. If you look at its definition, it only supports the ability to 'enumerate'. You're looking for an interface, and an underlying type, that supports the ability to add types to some kind of collection. If you look at ICollection<T>
you'll find it builds on IEnumerable<T>
's enumeration abilities, adding support for managing the content of a collection. The typical type used for this purpose is List<T>
. I would start there, populating your List<Person>
with objects. Once you have this list of Person
, you can use the interfaces List<T>
implements to control how it's used. For example, if you only want to offer enumeration support on your List<Person>
, you can cast it to IEnumerable<Person>
, narrowing the focus.
var myPeople = new List<Person>();
/// populate the list
myPeople.Add(new Person());
/// provide 'focussed' interface to underlying type
IEnumerable<Person> enumerablePeople = myPeople;
There are other types that implement ICollection<T>
with varying specialities, however, List<T>
is probably the simplest starting point for what you need.
CodePudding user response:
There is the IEnumerable.Append. This is great if you want to tack on one additional item to a large list without making a full copy, but it is not appropriate to use when adding many items.
I would probably suggest using an iterator block
public IEnumerable<Person> GetData(){
...
var lines = file.Skip(1);
foreach(var line in lines){
var cells = line.Split(';');
var person = new Person(...);
yield return person;
}
}
This is a easy and compact way to write a lazy reader that processes data as it is needed. But be aware that this parsing will be done each time the IEnumerable is iterated over. So in many cases the first thing you do is convert it to a list anyway.
I would be careful about claims about memory management. If you are processing huge files, some kind of streaming solution like this can indeed be critical, but you need to be really careful so that you never need to keep all of the file in memory. However, when processing small files it might very well be more efficient to do all the processing in one go. Or do something in between, like processing chunks of data. It really depends on what your use case is and what the memory and performance requirements are.