在C#中,我应该按值传递参数并返回相同的变量,或者通过引用传递?

时间:2014-12-02 18:25:21

标签: c# methods pass-by-reference argument-passing pass-by-value

在C#程序中,我创建了一个从列表中删除对象的方法。用户输入要删除的项目的索引,然后要求用户确认删除,如果用户确认,则该项目将从列表中删除,否则列表保持不变。
我不确定将参数传递给方法的最佳方法。我尝试通过引用传递列表(作为out参数):

static void DeleteCustomer(out List<Customer> customers)
{
    // ...display list of objects for user to choose from...
    int deleteId = ReadInt("Enter ID of customer to delete: ");
    Console.Write("Are you sure you want to delete this customer?");
    if (Console.ReadLine().ToLower() == "y")
    {
        customers.RemoveAt(deleteId);
    }
}

以上代码无效,因为我收到错误使用未分配的本地变量&#39;客户&#39; out参数&#39;客户&# 39;必须在控制离开当前方法之前指定。我以为我可以按值传递列表并返回相同的列表,如下所示:

static List<Customer> DeleteCustomer(List<Customer> customers)
{
    int deleteId = ReadInt("Enter ID of customer to delete: ");
    Console.Write("Are you sure you want to delete this customer?");
    if (Console.ReadLine().ToLower() == "y")
    {
        customers.RemoveAt(deleteId);
    }
    return customers;
}

// ...which would be called from another method with:
List<Customer> customers = DeleteCustomer(customers);

但这似乎并不高效,因为相同的变量按值传递然后返回。

在这种情况下传递参数的最有效方法是什么?

2 个答案:

答案 0 :(得分:4)

像所有引用类型一样,

List作为引用传递给对象,而不是它的副本。

请注意,这与通过引用引用非常不同,因为这意味着参数的赋值传播给调用者,而不是

这意味着对对象的修改(例如由RemoveAt执行的修改)将自动传播给调用者。

因此,只需通过它;无需返回值或out / ref参数。

您很少会将out / ref用于参考类型,并且当用于值类型时,性能差异将会非常小而且不会让您担心,除非你已经分析并确定确定那里出现问题。使用最具惯用意义的东西。

答案 1 :(得分:2)

在C#中,参数按值传递。这意味着当您将参数传递给方法时,会传递参数的副本。 C#具有按值(如int)和引用(如任何类)的类型。 C#包含一个堆栈(当推送所有可变的时候)和一个堆。值类型的值直接在此堆栈中推送,而引用类型的引用在堆栈中推入,并且引用的值在堆中被推送。
传递引用类型(如List)时,它会复制引用,但此副本指向列表中的同一对象。因此,任何更改都会直接影响对象,除非您更改引用(使用assigmet),但这不是您的情况。

这可以通过您的代码:

    static void DeleteCustomer<T>(List<T> customers)
    {
        Console.WriteLine("Enter ID of customer to delete: ");
        int deleteId;
        if (int.TryParse(Console.ReadLine(), out deleteId)) // if the input is an int
        {
            Console.Write("Are you sure you want to delete this customer?");
            if (Console.ReadLine().ToLower() == "y")
            {
                customers.RemoveAt(deleteId);
            }
        }
        else
        {
            Console.WriteLine("This is not valid Id");
        }
    }

如果您想了解ref an out关键字,我也可以帮助您,但是这个例子不是必需的。