条件语句、泛型委托不必要的强制转换

发布于 2024-11-30 00:02:07 字数 730 浏览 2 评论 0原文

在设置 Action 值时,我遇到了条件语句的非常奇怪的问题。这并不是说我不知道​​如何解决这个问题,因为使用普通的 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;
    }

所以也许您可以将问题理解为,为什么需要强制转换?

I'm having this really weird problem with a conditional statement when setting an Action<T> value. It's not that I don't know how to work around this as it's pretty easy to solve by using a normal if.

Here's my problem:

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)
    {

    }
}

This gives me a compiler error with the message

There's no implicit conversion between 'method group' and 'method group'.

Which is strange as I can't figure out why this would be illegal.

By the way, the below syntax will make this valid (from the compilers point of view):

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

So maybe you can read the question as, why is the cast necessary?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

猛虎独行 2024-12-07 00:02:07

您混淆了两个相似的概念:

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

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

因此,在第一个示例中,表达式在一侧返回一个方法组 B,在另一侧返回另一个方法组 C。三元运算符需要在两侧返回相同的类型,但它不知道将两侧转换为什么;您将结果分配给的变量类型 (Action) 并不决定表达式的类型。所以说是暧昧的。

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

You're conflating two similar concepts:

A) A method group. A method group is one or more C# methods with the same name. It's an abstraction used primarily by the compiler; you can't pass around a method group. All you can do with a method group is invoke it or create a delegate out of it. You can implicitly create a delegate from a method group if the type signatures match.

B) A delegate. You know what a delegate is; it has a specific type signature and refers directly to a method. As well as invoking it, you can pass it around and treat it as a first-class object.

So in the first example, your expression returns a method group B on the one side and another method group C on the other side. The ternary operator needs to return the same type on both sides, but it doesn't know what to cast either side to; the variable type you assigned the result to (Action<bool>) doesn't determine the type of the expression. So it's ambiguous.

In the second example, you legally cast the method group B to an Action<bool> delegate on the one side of the ternary operator. In the process of trying to disambiguate the expression, the compiler tries to cast each side to the type of the other side. It can successfully cast method group C to an Action<bool>, so it does so and the expression is legal.

神妖 2024-12-07 00:02:07

因为 BC 实际上并不是委托。它们是方法组,并且可以隐式转换为委托(特别是 Action),但这不是同一回事。

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

同样,它不能(或者至少)查看赋值运算符的另一边并说“哦,它应该是动作”。

添加强制转换时,左侧分支表达式的类型变为 Action,并且另一侧的方法组与该委托之间存在隐式转换,所以编译器又高兴了:整个表达式的类型是 Action

Because B and C aren't actually delegates. They're method groups, and they can be implictly converted to delegates (in particular Action<bool>), but that's not the same thing.

The type of the conditional expression must be consistent on both branches, and since B and C are currently method groups (which are not typed,) the compiler can't figure out what the type should be. As it tells you, there's no implicit conversion between them.

As well, it can't (or at least doesn't) look over to the other side of the assignment operator and say "oh, it should be Action<bool>".

When you add a cast, the type of the left branch expression becomes Action<bool>, and there is an implicit conversion between the method group on the other side and that delegate, so the compiler is happy again: the type of the entire expression is Action<bool>.

内心激荡 2024-12-07 00:02:07

我认为,埃里克会再次告诉我,我的推理有点不正确,但无论如何我都会尝试一下并希望他的纠正:-)

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

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

但是,正如您在链接的问题中看到的那样,三元表达式尝试找到表达式两个部分都匹配的返回类型。它不知道稍后应该发生到 Action 的转换。由于方法组本身不是类型,因此它们之间不存在转换,并且 B 无法转换为 C,因此编译器会抱怨这一点。

通过将三元表达式的任何部分转换为 Action,您可以告诉编译器返回类型应该是该类型,并且它会检查三元表达式的其他部分是否支持隐式转换为该类型。因为是这种情况,所以代码会编译。

I think, Eric will again tell me, that my reasoning is slightly incorrect, but I will give it a try anyway and hope for his correction :-)

A method group, for example B, doesn't have a type, it isn't an object (B.GetType() isn't going to compile).
It can easily be converted into a type, that's why an implicit cast exists.
Sample:

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

However, as you can see in the linked question, the ternary expression tries to find a return type that both parts of the expression match. It doesn't know that later a conversion to Action<bool> should happen. Because method groups are no types per se, there exists no conversion between them and B can't be converted to C and thus, the compiler complains just about that.

By casting any of the parts of the ternary expression to Action<bool>, you tell the compiler, that the return type should be that type and it checks whether the other part of the ternary expression supports an implicit cast to that type. Because this is the case, the code will compile.

国际总奸 2024-12-07 00:02:07

Action 是一个特定的委托类,并且不存在来自/到具有类似签名的常规委托的隐式转换。

An Action is a specific delegate class, and there isnt an impicit conversion available from/to a regular delegate with a similar signature.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文