out参数必须在控件离开当前方法之前赋值

本文关键字:方法 赋值 离开 控件 参数 out | 更新日期: 2023-09-27 18:06:52

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

out参数必须在控件离开当前方法之前赋值

通过将参数声明为out,您向调用者(和编译器)"承诺"您的方法将为该参数提供的变量设置值

因为你答应了,所以通过方法的每个路径都必须给这个参数赋值。

您的方法分配值给tourists。这实际上可能导致NullReferenceExceptiontourists.Add(...)如果方法被调用的null引用。

对我来说,似乎你可以在Main中初始化tourists时提交out关键字。注意 ReadData只修改列表的内容,而不是存储在tourists变量中的引用。由于您不想更改该引用(变量的值),因此不需要out关键字。

如果您希望ReadData初始化它,您需要添加

tourists = new List<Tourist>()

ReadData foreach循环之前


根据您的代码,更好的解决方案是将任何参数提交给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