c# - 使用匿名函数初始化委托
问题描述
我有一些以各种模型存在的硬件,并且正在编写可以使用各种 GUI 控制它的软件。我有一个表示硬件的类,它具有电压、速率、大小等属性。我想通过创建如下所示的类来简化对这些属性的访问:
public class CProperty
{
public CProperty(string name, Func<object> get, Action<object> set)
{
this.name = name;
this.get = get;
set = set;
}
private string name;
public Func<object> get;
public Action<object> set;
private object value;
}
然后我可以初始化一个数组,如下所示:
public CProperty[] Properties = new CProperty[]
{
new CProperty(
"name1",
new Func<float>(() => value),
new Action<float>((v) => value = v)
),
};
然后可以将该数组制作成一个带有索引器的集合类,该索引器使用属性名称作为索引。但是当我尝试这样做时,在数组初始化中,字段“值”不在 set 和 get 函数的初始化程序的范围内,我不明白为什么。
解决方案
您不能将 a 转换Func<float>
为 a ,Func<object>
也不能将 a 转换Action<float>
为Action<object>
。这是因为协变和逆变不能很好地与值类型一起使用(最后,协变和逆变是花招,不是类型之间的真正转换,因此要求两种类型具有相同的内存布局......参考是一个引用,因此很容易在两个引用之间进行协变/逆变,但是 a是一个值类型,这与作为一个引用类型的 afloat
非常不同)object
CProperty
在这两种情况下,您都应该向Func/Action
, like中添加一个类型的参数Func<CProperty, float>(cp => cp.value)
,但value
必须是public
...这是因为匿名方法是“静态的”,它们无法自由访问this
引用,因此您必须将其作为范围...
public class CProperty
{
public CProperty(string name, Func<CProperty, object> get, Action<CProperty, object> set)
{
this.name = name;
this.get = get;
this.set = set;
}
private string name;
public Func<CProperty, object> get;
public Action<CProperty, object> set;
public object value;
}
var properties = new CProperty[]
{
new CProperty(
"name1",
new Func<CProperty, object>(cp => cp.value),
new Action<CProperty, object>((cp, v) => cp.value = v)
),
};
或者您甚至可以捕获this
:
public class CProperty
{
public CProperty(string name, Func<CProperty, Func<object>> get, Func<CProperty, Action<object>> set)
{
this.name = name;
this.get = get(this);
this.set = set(this);
}
private string name;
public Func<object> get;
public Action<object> set;
public object value;
}
var properties = new CProperty[]
{
new CProperty(
"name1",
cp => new Func<object>(() => cp.value),
cp => new Action<object>((v) => cp.value = v)
),
};
最后,我认为你离你想要的还很远……你必须和CProperty
班级一起回到设计板。
推荐阅读
- types - 运行过滤器功能时出现“类型”错误
- python - 使用 python 代码处理 yahoo Finance api 限制
- oracle - 如果结果集中不存在,则使用 Oracle 模型子句向结果集中添加一行
- azure - Spark Delta Table 在中间 Schema Evolution 中添加新列
- r - 尝试从 R(Windows 10 和 Git Bash)运行脚本时出现“找不到命令”错误
- java - Spring Boot:是否可以将对象列表作为 QueryParameter 发送?
- c# - POST 到 API 的 400 错误请求
- docusignapi - Docusign 响应式签名文本选项卡
- r - How to use numbers in another vector to specify the name of a matrix in R?
- spring-boot - 将集成测试用例与构建分离的最佳方法(gradle spring-boot)