是否可以将操作隐式分配给无效委托
本文关键字:分配 无效 操作 是否 | 更新日期: 2023-09-27 18:11:44
我有一个类,需要使用 void 委托来构造:
//an object that's constructed with a "void delegate of no params"
public class BindableCommand
{
public delegate void ExecuteMethod();
private readonly ExecuteMethod _executeMethod;
public BindableCommand(ExecuteMethod executeMethod)
{
_executeMethod = executeMethod;
}
}
当它以以下方式构造时,它工作:
public class Test
{
public static void Main()
{
//creates a bindable command
BindableCommand b = Create();
}
private static BindableCommand Create(){
BindableCommand b = new BindableCommand(Function);
return b;
}
private static void Function(){}
}
我现在想在构建BindableCommand
之前Function
作为参数传递。
我的尝试编译失败:
public class Test
{
public static void Main()
{
//creates a bindable command
BindableCommand b = Create(Function);
}
private static BindableCommand Create(Action action){
BindableCommand b = new BindableCommand(action);
return b;
}
private static void Function(){}
}
prog.cs(20,19): warning CS0219: The variable `b' is assigned but its value is never used
prog.cs(24,23): error CS1502: The best overloaded method match for `BindableCommand.BindableCommand(BindableCommand.ExecuteMethod)' has some invalid arguments
prog.cs(9,12): (Location of the symbol related to previous error)
prog.cs(24,43): error CS1503: Argument `#1' cannot convert `System.Action' expression to type `BindableCommand.ExecuteMethod'
但我认为Action
是void delegate()
?
我无法传递无效委托:
private static BindableCommand Create(delegate void action){/* ... */}
看来我必须执行以下操作:
private static BindableCommand Create(BindableCommand.ExecuteMethod action){/* ... */}
有没有办法让强制转换自动发生?
您希望 C# 具有的功能称为"结构委托转换"。也就是说,如果您有两个委托类型,并且它们都采用 int 并返回一个字符串,那么您应该能够将一种类型的值分配给另一种类型。
C# 没有此功能。许多人(包括我自己(都对 .NET 1.0 中的委托没有引入结构类型感到遗憾。那为什么没有包括在内呢?
设计注意事项是,您可能希望在委托类型中编码语义信息:
delegate R Pure<A, R>(A a);
delegate R Impure<A, R>(A a);
"纯"函数是没有副作用的函数,其中输出由输入唯一决定。例如,您可能想说比较函数必须是纯函数。如果输入没有变化,我们不希望比较改变其值,也不期望它产生副作用。
显然,能够将不纯委托值分配给纯委托类型的变量是错误的。 因此,即使委托在结构上相同,类型系统也会阻止它。
在实践中,很少有人将这样的语义信息放在委托中。允许结构转换会更方便。
有一种方法可以在结构委托类型之间进行转换,但它不是很好:
Action a = whatever;
ExecuteMethod e = a.Invoke;
也就是说,为 e
创建的委托是委托a
的调用方法的委托。 因此调用e
调用a
,这会调用所需的方法。这是一个额外的间接步骤,但性能损失不会太大,人们希望。
但我认为
Action
是void delegate()
?
是的。 这并不意味着具有相同签名的委托实例之间存在隐式转换。
有没有办法让强制转换自动发生?
不。 您可以只使用 Action
而不是首先定义自己的委托,在这种情况下不需要转换,但如果要创建自己的委托类型,则需要将其显式转换为另一个委托,而不考虑委托的签名。