【问题标题】:Conditional statement, generic delegate unnecessary cast条件语句,泛型委托不必要的强制转换
【发布时间】:2011-08-16 14:04:50
【问题描述】:

在设置Action<T> 值时,我遇到了一个非常奇怪的条件语句问题。并不是我不知道如何解决这个问题,因为使用普通的if 很容易解决。

这是我的问题:

public class Test
{
    public bool Foo { get; set; }
    public Action<bool> Action { get; set; }

    public void A()
    {
        Action = Foo ? B : C;//Gives compiler error
    }

    public void B(bool value)
    {

    }

    public void C(bool value)
    {

    }
}

这给了我一个编译器错误消息

“方法组”和“方法组”之间没有隐式转换。

这很奇怪,因为我不知道为什么这是非法的。

顺便说一句,下面的语法将使它有效(从编译器的角度来看):

    public void A()
    {
        Action = Foo ? (Action<bool>) B : C;
    }

所以也许你可以把这个问题理解为,为什么需要演员表?

【问题讨论】:

    标签: c# generics compiler-construction delegates


    【解决方案1】:

    您将两个相似的概念混为一谈:

    A) 一个方法组。方法组是一个或多个具有相同名称的 C# 方法。它是主要由编译器使用的抽象;你不能传递一个方法组。您对方法组所能做的就是调用它或从中创建一个委托。如果类型签名匹配,您可以从方法组隐式创建委托。

    B) 代表。你知道什么是委托;它具有特定的类型签名并直接引用方法。除了调用它,您还可以传递它并将其视为一等对象。

    所以在第一个示例中,您的表达式在一侧返回一个方法组B,在另一侧返回另一个方法组C。三元运算符需要在两边都返回相同的类型,但它不知道将任何一方转换为什么;您将结果分配给 (Action&lt;bool&gt;) 的变量类型不能确定表达式的类型。所以它是模棱两可的。

    在第二个示例中,您合法地将方法组B 强制转换为三元运算符一侧的Action&lt;bool&gt; 委托。在尝试消除表达式歧义的过程中,编译器尝试将每一侧转换为另一侧的类型。它可以成功地将方法组C 转换为Action&lt;bool&gt;,所以它这样做并且表达式是合法的。

    【讨论】:

      【解决方案2】:

      因为BC 实际上并不是代表。它们是方法组,可以隐式转换为委托(特别是 Action&lt;bool&gt;),但那不是一回事。

      条件表达式的类型必须在两个分支上保持一致,并且由于BC 当前是方法组(没有类型),编译器无法确定类型应该是什么。正如它告诉你的那样,它们之间没有隐式转换。

      同样,它不能(或者至少不能)查看赋值运算符的另一边并说“哦,应该是Action&lt;bool&gt;"。

      当你添加一个强制转换时,左分支表达式的类型变为Action&lt;bool&gt;,并且在另一端的方法组和那个委托之间存在一个隐式转换,所以编译器是再次高兴:整个表达式的类型是Action&lt;bool&gt;

      【讨论】:

        【解决方案3】:

        我想,Eric will again tell me, that my reasoning is slightly incorrect,但无论如何我都会试一试,希望他的纠正:-)

        一个方法组,例如B,没有类型,它不是一个对象(B.GetType() 不会编译)。
        它可以很容易地转换为类型,这就是存在隐式强制转换的原因。 示例:

        Action<bool> a = B; // implicit cast taking place.
        

        但是,正如您在链接的问题中看到的那样,三元表达式试图找到表达式的两个部分都匹配的返回类型。它不知道以后应该转换为Action&lt;bool&gt;。因为方法组本身不是类型,所以它们之间不存在转换,B 不能转换为C,因此编译器会抱怨这一点。

        通过将三元表达式的任何部分强制转换为Action&lt;bool&gt;,您告诉编译器返回类型应该是该类型,并且它会检查三元表达式的另一部分是否支持对该类型的隐式强制转换。因为是这种情况,所以代码会编译。

        【讨论】:

          【解决方案4】:

          Action 是一个特定的委托类,不存在与具有类似签名的常规委托之间的隐式转换。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-04-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-12-01
            • 1970-01-01
            相关资源
            最近更新 更多