引用类型函数参数在函数 try catch 块后不保留更改

Reference type function argument does not retain changes after function try catch block

下面的代码。

我完全理解引用类型和值类型。 [更正,我不完全理解引用类型与值类型。]

今天我 运行 遇到了一些奇怪的事情。
我声明了一个数据表 class var 并将其初始化为 null。
我创建函数:GetAutoAllocationResult(in int, datatable, out string)
我将数据表 class var 传递给函数。
我在 TRY/CATCH 块中进行了一些条件更改。
我从函数return.
数据表不保留函数内的更改。
如果我在数据表的函数签名中使用 OUT 关键字,它会保留更改。
什么?

DataTable auto_allocation_result = null;

// ...


// get the data from the stored procedure return
string auto_allocation_query_result_message = string.Empty;
bool is_auto_allocation_result_query_successful = false;
is_auto_allocation_result_query_successful = GetAutoAllocationResult(auto_allocation_record_uid, 
                        auto_allocation_result, out auto_allocation_query_result_message);

//...


private bool GetAutoAllocationResult(in int p_auto_allocate_record_uid, DataTable p_return_data, string p_message)
{
    bool is_successful = false;
    p_return_data = new DataTable();
    p_message = string.Empty;

    string sql = some select statement

    SqlCommand sc = new SqlCommand();
    sc.Connection = some sql connection
    sc.CommandText = sql;


    // add parameters
    SqlParameter sqlparam_order_ship_loc_uid = sc.Parameters.Add("@order_ship_loc_uid", SqlDbType.Int);
    sqlparam_order_ship_loc_uid.Value = p_auto_allocate_record_uid;
    


    // run query
    try
    {
        SqlDataAdapter sda = new SqlDataAdapter(sc);
        sda.Fill(p_return_data);   // p_return_data DOES NOT RETAIN DATA AFTER FUNCTION CALL IF OUT KEYWORD IS NOT USED

        if (p_return_data != null)
        {
            if (p_return_data.Rows.Count <= 0)
            {
                p_return_data = null;

                p_message =
                    $"Could not perform auto-allocation.  Please provide IT with the information below.{Environment.NewLine}" +
                    $"{Environment.NewLine}" +
                    $"No auto allocation rows returned for UID ({p_auto_allocate_record_uid}).";

                is_successful = false;
            }
            else
            {
                is_successful = true;
            }
        }
        else
        {
            p_message =
                $"Could not perform auto-allocation.  Please provide IT with the information below.{Environment.NewLine}" +
                $"{Environment.NewLine}" +
                $"Auto allocation query did not instantiate a datatable ({p_auto_allocate_record_uid}).";

            is_successful = false;
        }
    }
    catch (Exception ex)
    {
        p_message =
            $"Failed to perform auto-allocation.  Please provide IT with the information below.{Environment.NewLine}" +
            $"{Environment.NewLine}" +
            $"There was an error querying auto allocation result data.{Environment.NewLine}" +
            $"Exception Message: ({ex.Message}){Environment.NewLine}" +
            $"Inner Exception: ({ex.InnerException}){Environment.NewLine}" +
            $"Stack Trace: ({ex.StackTrace})";

        is_successful = false;
    }


    return is_successful;            
}

您需要将其设置为新的DataTable,而不是函数外的null。请记住,引用是指向内存对象的指针。但是引用本身是按值传递的(在 stack/copied 上)。因此,您传入了一个不指向内存对象 (null) 的引用,并且副本已分配给函数内的 DataTable。当函数完成时,副本将从 stack/disgarded 中删除,DataTable 将进入垃圾收集器。

如果您没有经验,很容易犯这个错误。但现在你应该对你未来的编码乐趣有了更好的了解。