微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用三元运算符分配动作 c#

如何解决使用三元运算符分配动作 c#

我想有条件地执行一个动作,所以我决定将它重新分配给一个函数,如下所示:

public void ActionReassingnment1(bool doIt) {
    bool myBool = true;
    Action myAction = () => { myBool = false; };
    myAction = doIt ? myAction : () => { };
}

我使用 myBool 作为我的示例 lambda 不为空,只是占位符没有意义的逻辑。 问题是,如果没有中间变量 myAction,我无法直接在 true 语句中使用三元运算符进行赋值,如下所示:

public void ActionReassingnment2(bool doIt)
{
    bool myBool = true;
    //Action myAction = () => { myBool = false; };
    myAction = doIt ? () => { myBool = false; }; : () => { }; //Error here
}

由于 ; lambda 的 () => { myBool = false; };,我获得了预期的 :。有道理,但是无论我尝试什么,我都无法直接适应 lambda。

我尝试用 (() => { myBool = false; };){() => { myBool = false; };} 包装 lambda,但没有成功。

很多时候我得到的编译错误type of conditional expression cannot be determined because there is no implicit conversion between 'lambda expression' and 'lambda expression'

令我惊讶的是,在错误的陈述中,lambda 是合适的。

可以在三元运算符的 true 语句中分配 lambda 吗?如果是这样,如何?如果不是,那为什么是在虚假陈述中?

解决方法

三元运算符通常无法确定左侧/右侧结果类型。

具体来说,您将无法编写:

xxx ? () => { } : () => { }

因为 ()=>{} 在 C# 中没有特定类型。例如,此表达式可以自动转换为 System.Action,但如果没有任何提示,编译器不会猜测它必须这样做。有了上面的这种确切形式,就没有提示了。

在这种情况下,请尝试更具体,尽可能少地推断,这通常会解决问题。

var myAction = doIt ? new Action(() => { myBool = false; }) : new Action(() => { });

或者这也可以:

var myAction = doIt ? new Action(() => { myBool = false; }) : () => { }; // should work

甚至

Action myAction = doIt ? () => { myBool = false; } : () => { }; // really doubtful,probably not

因为它至少在一个地方有一个特定的类型,所以可以推断出其他方面。不过我不确定,我没有用真正的编译器检查过它。带有两个新动作的第一个版本肯定会起作用。

就您而言,; 之前的额外 : 也存在问题。

在对它进行脱线并以一种有点奇怪的方式格式化之后,它是:

var myAction =
    doIt
    ? new Action(() => { myBool = false; })
    : new Action(() => { })
    ;

在这里您可以看到,每个 lambda 表达式都是一个干净的 ()=>{ },没有后面的 ;,并且 ?: 的格式为 condition ? whentrue : whenfalse 并且 {{ 1}} 仅位于整个 ; 表达式的末尾。

--

编辑:既然你问过像这样的演员

var foo = value;

请注意,它看起来或多或少相同,就像任何其他 lambda+?: 一样不可读,并且与以下代码相比:

var myAction = doIt ? (Action)(() => { myBool = false; }) : () => { };

使用强制转换,您仍然需要提供 Action 的完整类型名称,并在 lambda 周围使用括号,因此区别仅在 var myAction = doIt ? new Action(() => { myBool = false; }) : () => { }; new 之间,因此为 2 个字符。除非绝对必要,否则我通常不使用强制转换,因此我会在这里使用 ()

此外,由于 new + lambdas 很快变得难以辨认,而且由于 ?: 回退实际上是一个完全可重用的无操作,因此没有太多理由创建大量这样的委托对象,所以我的代码实际上可能看起来像这样:

()=>{}

或者,如果由于某种原因,它不能重复使用,那么:

// elsewhere in some utility class
public static readonly Action NoOp = () => { };

...

var myAction = !doIt ? Utils.NoOp : () => { myBool = false; };

// or,if code block is larger

var myAction = !doIt ? Utils.NoOp : () => {
    logic logic
    myBool = false;
    logic logic
};

我知道最后一个直接打破了你把它放在一行的最初想法,但既然我已经讨论了不同的格式和代码布局,那么,真的。在一行中超过一个 lambda 对可读性非常不利,除非这些 lambda 是微不足道的,否则您的同事或该代码的未来读者可能会感谢这种扩展的布局:)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。