引用类型函数参数在函数 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 将进入垃圾收集器。
如果您没有经验,很容易犯这个错误。但现在你应该对你未来的编码乐趣有了更好的了解。
下面的代码。
我完全理解引用类型和值类型。 [更正,我不完全理解引用类型与值类型。]
今天我 运行 遇到了一些奇怪的事情。
我声明了一个数据表 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 将进入垃圾收集器。
如果您没有经验,很容易犯这个错误。但现在你应该对你未来的编码乐趣有了更好的了解。