C# 和 ref/out 中的 Lambda
Lambda in C# and ref/out
我有一些从与通信总线接口的 DLL 导入的类似 set/get 函数。理想情况下,这些都应该共享一个相同的包装器来执行一些错误检查、互斥处理等。下面的代码片段是它的基本表示。它编译并且所有功能似乎都有效,除了 WrappedGet() 不修改引用的变量数据。想法?
static UInt32 common_var = 0;
// Reduce boilerplate by wrapping all calls to the DLL with this
static private bool CommonWrapper<T1>(Action<T1> dll_function_handle, ref T1 data)
{
// Commmon code for mutex handling etc
/// ....
// Call to function handle, sometimes data is in-parameter, other times out-param
dll_function_handle(data);
return true;
}
static private void DllSet(UInt32 data) { common_var = data; }
static public void WrappedSet(UInt32 data) { CommonWrapper<UInt32>((UInt32 a) => DllSet(a), ref data); }
static private void DllGet(ref UInt16 data){ data = 1234; }
// WrappedGet does not modify argument "data" because of the lambda? What to do?
static public void WrappedGet(ref UInt16 data) { CommonWrapper<UInt16>((UInt16 a) => DllGet(ref a), ref data); }
编辑:
这个有效:
static public void WrappedGet(ref UInt16 data)
{
UInt16 local = 0;
CommonWrapper<UInt16>((UInt16) => DllGet(ref local), ref data);
data = local;
}
虽然有点尴尬,但这样做正确吗?
您代码中的问题是 Action 没有将参数作为 ref
,因此在将 data
提供给 DllGet
方法之前将创建一个副本.
// vvvvvvvvvvvvvvvvvvvvvvvvvvv
CommonWrapper<UInt16>((UInt16 a) => DllGet(ref a), ref data);
您可以定义委托并在 lambda 中使用 ref
而不是 Action
。
所以你需要添加一个委托
private delegate void WrappedFunction<T>(ref T data);
并且需要在CommonWrapper
中使用
// vvvvvvvvvvvvvvvvvvv
static private bool CommonWrapper<T1>(WrappedFunction<T1> dll_function_handle, ref T1 data)
{
// Your code here
}
并且您需要将 ref
添加到 lambda
// vvv
static public void WrappedGet(ref UInt16 data) { CommonWrapper<UInt16>((ref UInt16 a) => DllGet(ref a), ref data); }
所以整个代码如下所示:
private delegate void WrappedFunction<T>(ref T data);
// Reduce boilerplate by wrapping all calls to the DLL with this
static private bool CommonWrapper<T1>(WrappedFunction<T1> dll_function_handle, ref T1 data)
{
// Commmon code for mutex handling etc
// ....
// Call to function handle, sometimes data is in-parameter, other times out-param
dll_function_handle(ref data);
return true;
}
static private void DllSet(UInt32 data) { common_var = data; }
static public void WrappedSet(UInt32 data) { CommonWrapper<UInt32>((ref UInt32 a) => DllSet(a), ref data); }
static private void DllGet(ref UInt16 data){ data = 1234; }
static public void WrappedGet(ref UInt16 data) { CommonWrapper<UInt16>((ref UInt16 a) => DllGet(ref a), ref data); }
根据我的评论,这是与您的原始代码最相似的解决方案:
class TEST
{
static UInt32 common_var = 0;
// Reduce boilerplate by wrapping all calls to the DLL with this
static private bool CommonWrapper<T1>(Action<T1> dll_function_handle, ref T1 data)
{
dll_function_handle(data);
return true;
}
static private bool CommonWrapper<T1>(Func<T1, T1> dll_function_handle, ref T1 data)
{
data = dll_function_handle(data);
return true;
}
static private void DllSet(UInt32 data) { common_var = data; }
static public void WrappedSet(UInt32 data) { CommonWrapper<UInt32>((UInt32 a) => DllSet(a), ref data); }
static private void DllGet(ref UInt16 data) { data = 1234; }
static public void WrappedGet(ref UInt16 data) { CommonWrapper<UInt16>((UInt16 a) => { DllGet(ref a); return a; }, ref data); }
}
就个人而言,如果丢弃任何输入值,我会避免使用 ref
参数。我会改为将参数声明为 out
或为方法声明 return 类型;这样,Func<T1,T1>
应该可以替换为更简单的 Func<T1>
.
我有一些从与通信总线接口的 DLL 导入的类似 set/get 函数。理想情况下,这些都应该共享一个相同的包装器来执行一些错误检查、互斥处理等。下面的代码片段是它的基本表示。它编译并且所有功能似乎都有效,除了 WrappedGet() 不修改引用的变量数据。想法?
static UInt32 common_var = 0;
// Reduce boilerplate by wrapping all calls to the DLL with this
static private bool CommonWrapper<T1>(Action<T1> dll_function_handle, ref T1 data)
{
// Commmon code for mutex handling etc
/// ....
// Call to function handle, sometimes data is in-parameter, other times out-param
dll_function_handle(data);
return true;
}
static private void DllSet(UInt32 data) { common_var = data; }
static public void WrappedSet(UInt32 data) { CommonWrapper<UInt32>((UInt32 a) => DllSet(a), ref data); }
static private void DllGet(ref UInt16 data){ data = 1234; }
// WrappedGet does not modify argument "data" because of the lambda? What to do?
static public void WrappedGet(ref UInt16 data) { CommonWrapper<UInt16>((UInt16 a) => DllGet(ref a), ref data); }
编辑:
这个有效:
static public void WrappedGet(ref UInt16 data)
{
UInt16 local = 0;
CommonWrapper<UInt16>((UInt16) => DllGet(ref local), ref data);
data = local;
}
虽然有点尴尬,但这样做正确吗?
您代码中的问题是 Action 没有将参数作为 ref
,因此在将 data
提供给 DllGet
方法之前将创建一个副本.
// vvvvvvvvvvvvvvvvvvvvvvvvvvv
CommonWrapper<UInt16>((UInt16 a) => DllGet(ref a), ref data);
您可以定义委托并在 lambda 中使用 ref
而不是 Action
。
所以你需要添加一个委托
private delegate void WrappedFunction<T>(ref T data);
并且需要在CommonWrapper
// vvvvvvvvvvvvvvvvvvv
static private bool CommonWrapper<T1>(WrappedFunction<T1> dll_function_handle, ref T1 data)
{
// Your code here
}
并且您需要将 ref
添加到 lambda
// vvv
static public void WrappedGet(ref UInt16 data) { CommonWrapper<UInt16>((ref UInt16 a) => DllGet(ref a), ref data); }
所以整个代码如下所示:
private delegate void WrappedFunction<T>(ref T data);
// Reduce boilerplate by wrapping all calls to the DLL with this
static private bool CommonWrapper<T1>(WrappedFunction<T1> dll_function_handle, ref T1 data)
{
// Commmon code for mutex handling etc
// ....
// Call to function handle, sometimes data is in-parameter, other times out-param
dll_function_handle(ref data);
return true;
}
static private void DllSet(UInt32 data) { common_var = data; }
static public void WrappedSet(UInt32 data) { CommonWrapper<UInt32>((ref UInt32 a) => DllSet(a), ref data); }
static private void DllGet(ref UInt16 data){ data = 1234; }
static public void WrappedGet(ref UInt16 data) { CommonWrapper<UInt16>((ref UInt16 a) => DllGet(ref a), ref data); }
根据我的评论,这是与您的原始代码最相似的解决方案:
class TEST
{
static UInt32 common_var = 0;
// Reduce boilerplate by wrapping all calls to the DLL with this
static private bool CommonWrapper<T1>(Action<T1> dll_function_handle, ref T1 data)
{
dll_function_handle(data);
return true;
}
static private bool CommonWrapper<T1>(Func<T1, T1> dll_function_handle, ref T1 data)
{
data = dll_function_handle(data);
return true;
}
static private void DllSet(UInt32 data) { common_var = data; }
static public void WrappedSet(UInt32 data) { CommonWrapper<UInt32>((UInt32 a) => DllSet(a), ref data); }
static private void DllGet(ref UInt16 data) { data = 1234; }
static public void WrappedGet(ref UInt16 data) { CommonWrapper<UInt16>((UInt16 a) => { DllGet(ref a); return a; }, ref data); }
}
就个人而言,如果丢弃任何输入值,我会避免使用 ref
参数。我会改为将参数声明为 out
或为方法声明 return 类型;这样,Func<T1,T1>
应该可以替换为更简单的 Func<T1>
.