Reputation: 1043
I'm very new C# and this is the first time I'm doing anything with a list, so this might be a very dumb question... I'm trying to read data from a file to a list that consists of Tourist
objects. As I understand I need to assign something to tourists
list before I add objects to it, but I'm not sure how to do that.
class Tourist
{
public string FirstName { get; set; }
public string LastName { get; set; }
public double Contributed { get; set; }
public Tourist(string firstName, string lastName, double money)
{
FirstName = firstName;
LastName = lastName;
Contributed = money * 0.25;
}
}
class Program
{
static void Main(string[] args)
{
List<Tourist> tourists = new List<Tourist>();
ReadData(out tourists);
}
static void ReadData(out List<Tourist> tourists)
{
const string Input = "..\\..\\Duomenys.txt";
string[] lines = File.ReadAllLines(Input);
foreach (string line in lines)
{
string[] values = line.Split(';');
string firstName = values[0];
string lastName = values[1];
double money = Double.Parse(values[2]);
tourists.Add(new Tourist(firstName, lastName, money));
}
}
}
Upvotes: 4
Views: 1945
Reputation: 37050
You have to provide a value for your out
-parameter before leaving the method
static void ReadData(out List<Tourist> tourists)
{
const string Input = "..\\..\\Duomenys.txt";
tourists = new List<Tourist>();
string[] lines = File.ReadAllLines(Input);
foreach (string line in lines)
{
string[] values = line.Split(';');
string firstName = values[0];
string lastName = values[1];
double money = Double.Parse(values[2]);
tourists.Add(new Tourist(firstName, lastName, money));
}
}
However as you´re passing a List<T>
which is a reference-type you don´t need the out
.keyword as modifications to the object that you´re referencing are reflected in all references.
So after calling ReadData
the list you´ve provided will change also:
var tourists = new List<Tourist>();
ReadData(toursists); // this changes the elements within the list
// do something with the list
Upvotes: 1
Reputation: 6310
Parameters with out
need to be assigned to in the body of the method and do not get their value carried over from the call site. Quoting msdn:
Within a method, just like a local variable, an output parameter is initially considered unassigned and must be definitely assigned before its value is used.
In your case there are three ways to solve it:
First, you can move assignment from caller to the method:
static void Main(string[] args)
{
List<Tourist> tourists;
ReadData(out tourists);
}
static void ReadData(out List<Tourist> tourists)
{
tourists = new List<Tourist>();
//...
}
Second, you can change your declaration to skip out
in the declaration entirely, which will carry the initiated value to the method and lift the requirement to assign it in that method.
Last option (and the best one IMO, in terms of readability) is to make the list a return value instead of out
parameter:
static void Main(string[] args)
{
List<Tourist> tourists = ReadData();
}
static List<Tourist> ReadData()
{
List<Tourist> tourists = new List<Tourist>();
//...
return tourists;
}
Upvotes: 2
Reputation: 43906
By declaring a parameter as out
you "promise" the caller (and the compiler) that your method will set a value to the variable provided as argument for that parameter.
Because you promise it, every path through your method must assign a value to this parameter.
Your method does not assign a value to tourists
. This may actually lead to a NullReferenceException
at tourists.Add(...)
if the method gets called with a null
reference.
To me it seems you can ommit the out
keyword as you initialize tourists
already in Main
. Note that ReadData
only modifies the content of the list, not the reference to it stored in the tourists
variable. Since you don't want to change that reference (the variable's value), you don't need the out
keyword.
If you want ReadData
to initialize it, you need to add the line
tourists = new List<Tourist>()
in ReadData
before the foreach
loop.
As your code stands, the better solution is to ommit any parameter to ReadData
and let the method return the list instead:
static List<Tourist> ReadData()
{
// create list
List<Tourist> tourists = new List<Tourist>();
const string Input = "..\\..\\Duomenys.txt";
string[] lines = File.ReadAllLines(Input);
foreach (string line in lines)
{
// shortened for brevity
tourists.Add(new Tourist(firstName, lastName, money));
}
return tourists; // return newly created list
}
And use this in Main
like:
static void Main(string[] args)
{
List<Tourist> tourists = ReadData();
}
Upvotes: 5