是否可以隐式将动作分配给void委托?

时间:2016-10-05 16:06:55

标签: c# function types casting delegates

我有一个需要用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(){}
}

我想在构建Function之前传递BindableCommand作为参数 我的尝试无法编译:

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'

但我认为Actionvoid delegate()

我无法传递空委托:

private static BindableCommand Create(delegate void action){/* ... */}

我似乎必须做以下事情:

private static BindableCommand Create(BindableCommand.ExecuteMethod action){/* ... */}

有没有办法让演员自动出现?

2 个答案:

答案 0 :(得分:13)

您希望C#拥有的功能称为"结构代理转换"。也就是说,如果你有两个委托类型并且它们都接受一个int并返回一个字符串,那么你应该能够将一种类型的值分配给另一种类型。

C#没有此功能。包括我自己在内的许多人都对.NET 1.0中的代表没有引入结构化类型表示遗憾。那为什么不包括在内?

设计考虑因素是您可能希望在委托类型中编码语义信息:

e

A"纯粹" function是一个没有副作用的函数,其输出由输入唯一确定。例如,您可能想说比较函数必须是纯粹的。如果输入没有改变,我们不希望进行比较以改变其价值,并且我们不希望它产生副作用。

显然,能够将不纯的委托值分配给纯委托类型的变量是错误的。因此类型系统会阻止它,即使代表在结构上完全相同。

在实践中,很少有人将这样的语义信息放在代表中。允许结构转换会更方便。

有一种方法可以在结构委托类型之间进行转换,但它不是很好:

a

也就是说,为e创建的委托是委托a的invoke方法的委托。因此调用{{1}}会调用{{1}} ,它调用所需的方法。这是间接的额外步骤,但人们希望性能损失不是太大。

答案 1 :(得分:3)

  

但我认为Actionvoid delegate()

是的。这并不意味着具有相同签名的委托实例之间存在隐式转换。

  

有没有办法让演员自动出现?

没有。你可以只使用Action而不是首先定义你自己的委托,在这种情况下不需要转换,但如果你想创建自己的委托类型,那么你需要明确地将它转换为另一个代表,无论代表的签名如何。