【问题标题】:Can an Action be assigned to a void delegate implicitly?可以将 Action 隐式分配给 void 委托吗?
【发布时间】:2016-10-05 16:06:55
【问题描述】:

我有一个需要用 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'

但我认为Actionvoid delegate()

我不能传递一个无效的委托:

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

看来我必须做到以下几点:

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

有没有办法让演员自动发生?

【问题讨论】:

标签: c# function types casting delegates


【解决方案1】:

您希望 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 的invoke 方法的委托。 所以调用e 会调用a,它会调用所需的方法。这是一个额外的间接步骤,但希望性能损失不会太大。

【讨论】:

    【解决方案2】:

    但我认为Actionvoid delegate()

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

    有没有办法让演员自动发生?

    没有。您可以只使用Action 而不是首先定义自己的委托,在这种情况下不需要转换,但是如果您想创建自己的委托类型,则需要将其显式转换为另一个委托,与代表的签名无关。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-15
      • 2019-12-25
      • 1970-01-01
      • 1970-01-01
      • 2011-09-29
      相关资源
      最近更新 更多