Параметр out должен быть назначен до того, как управление покинет текущие методы



Я очень новый C# , и это первый раз, когда я делаю что-то со списком, так что это может быть очень глупый вопрос... Я пытаюсь прочитать данные из файла в список, состоящий из объектов Tourist. Как я понимаю, мне нужно назначить что-то в список tourists, прежде чем добавлять в него объекты, но я не уверен, как это сделать.



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));
}
}
}
389   3  
c#

3 ответов:

Объявляя параметр как out, вы "обещаете" вызывающему объекту (и компилятору), что ваш метод установит значение переменной, предоставленной в качестве аргумента для этого параметра.

Поскольку вы это обещаете, каждый путь через ваш метод должен присваивать значение этому параметру.

Ваш метод не присваивает значение tourists. Это может фактически привести к NullReferenceException в tourists.Add(...), если метод вызывается со ссылкой null.

Мне это кажется, вы можете пропущены out сайта, как вы инициализировать tourists уже Main. обратите внимание , что ReadData изменяет толькосодержимое списка , а нессылку на него, хранящуюся в переменной tourists. Поскольку вы не хотите изменять эту ссылку (значение переменной ), вам не нужно ключевое слово out.

Если вы хотите ReadData инициализировать его, вам нужно добавить строку

tourists = new List<Tourist>()

В ReadData перед the foreach петля.


Поскольку ваш код стоит, лучшим решением будет ommit любой параметр в ReadData и пусть метод возвращает список вместо этого:

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
}

И использовать это в Main как:

static void Main(string[] args)
{
    List<Tourist> tourists = ReadData();
}

Параметры с out должны быть назначены в теле метода и не переносить их значение с сайта вызова. Цитирование msdn:

В методе, как и в локальной переменной, выходной параметр изначально считается неназначенным и должен быть определенно присвоен, прежде чем его значение будет использовано.

В вашем случае есть три способа решить эту проблему:

Во-первых, вы можете переместить назначение от вызывающего объекта к методу:

static void Main(string[] args)
{
    List<Tourist> tourists;
    ReadData(out tourists);
}

static void ReadData(out List<Tourist> tourists)
{
    tourists = new List<Tourist>();
    //...
}

Второй, вы можете изменить свое объявление на пропуск out в объявлении полностью, что перенесет инициированное значение в метод и отменит требование присвоить его в этом методе.

Последний вариант (и лучший ИМО, с точки зрения читаемости) - сделать список возвращаемым значением вместо параметра out:

static void Main(string[] args)
{
    List<Tourist> tourists = ReadData();
}

static List<Tourist> ReadData()
{
    List<Tourist> tourists = new List<Tourist>();
    //...
    return tourists;
}

Вы должны указать значение для вашего out-параметра, прежде чем покинуть метод

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));
    }
}

Однако, поскольку вы передаете List<T>, который является ссылочным типом, вам не нужен out.ключевое слово как модификация объекта, на который вы ссылаетесь, отражается в всех ссылках.

Поэтому после вызова ReadData список, который вы предоставили, также изменится:

var tourists = new List<Tourist>();
ReadData(toursists);  // this changes the elements within the list
// do something with the list

Comments

    Ничего не найдено.