如何解决使用三元运算符分配动作 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 举报,一经查实,本站将立刻删除。