我想我忘记了一些明显的事情,但如果它确认一个条件尽可能保持DRY,我似乎找不到分配值的方法...... 一些代码来解释我的意思......
a = (b > 1) ? b : c;
甚至a = (a > 1) ? a : b;
所以当然这里没什么大不了的,但如果要用方法调用替换,(可能是那里的收益率)或者其他什么,那么我就要调用它两次......
我唯一看到的就是把它放在一个变量中,然后就像上面的代码一样......
有更好的主意吗?
编辑以便更好地理解: 假设我在xml文件中搜索一个值,使用空检查(?。?[])等等,这样就像
string store_no = myXmlNode.SelectSingleNode("aChildNode")?.SelectSingleNode("myNode")?.Attributes?["store_no]?.Value;
所以在这里我将它存储在一个变量中,以便我可以稍后测试它的值。 如果我想检查特定的store_no!我必须做类似的事情
store_no = (store_no=="STORE23")? store_no : "unknown";
...是的,不确定这个例子是否足够明确,但这个想法就在这里;我可能不想将数据存储在变量(例如巨大的数据块)中是否有办法获得相同的结果?
答案 0 :(得分:8)
我想我忘记了一些明显的事情,但如果它确认一个条件尽可能保持DRY,我似乎找不到分配值的方法
让我们首先解除您的共同误解。
这完全是对DRY含义的误解。如果您有一个Customer
对象,并且您有一个Address
对象而Customer
有字段{{ 1}}和BillingCity
以及BillingPostalCode
等等,那么您的代码不是DRY,因为相同的信息在两个地方冗余地表示。您应该重新设计代码,以便HomeCity
包含Customer
个对象的集合。
现在,在整个节目中避免剪切和粘贴重复代码确实是一个好主意,但DRY是关于中到大规模的代码的设计。 DRY绝对不代表您的代码不应该在同一个表达式中两次使用相同的变量!
现在我们已经解决了这个问题,让我们来看看你对语言的批评。
我们经常处于“表达式上下文”的情况下 - 也就是说,一种长而可能流畅的表达方式,我们希望避免做多余的工作。例如,我们可能有:
Address
也许两次调用x = M() > 0 ? M() : 0;
是昂贵的,或者它可能不是幂等的。随你。无所谓。重点是,我们不想把它叫两次。
令人恼火的是,我们必须退出表达式上下文并进入语句环境:
M()
这当然是合法的,但有点令人烦恼。此外,在某些情况下,它可能很棘手:
var m = M();
x = m > 0 ? m : 0;
现在我们该怎么办?假设我们只想在N(P() ?? (M() > 0 ? M() : 0));
为空时调用M()
,没有明显的方法可以保留语义而不用长手写出来。
P()
YUCK。天哪,这太可怕了。
其他语言通过引入var t = default(T);
var p = P();
if (p == null) {
var m = M();
t = m > 0 ? m : 0;
} else {
t = p.Value;
}
N(t);
表达式来解决此问题。我们真正想要的是能够在表达式的中间引入一个新的局部。常见语法为let
,let ID = EXPRESSION in EXPRESSION
成为只读变量,具有特定含义,但仅在ID
范围内:
in
请注意,C# 支持N(P() ?? (let m = M() in m > 0 ? m : 0));
表达式,但仅支持查询理解。如果它在语言中更普遍地支持它会很棒。
多年来,有许多建议将let
表达式或其更通用的表达式,顺序表达式添加到C#中。有关示例,请参阅github roslyn问题跟踪器。也许这会进入C#8;如果你想要,请参加论坛。
那么你能做些什么呢?
事实证明是C#中的 let-expressions。 let
只是编写let x = y in z
的好方法。所以你可以写:
(((Func<X, Z>)(x=>z))(y))
但这看起来几乎是可怕的。这是一个难以理解的混乱。
问题是lambda。这会更好:
N(P() ?? (((Func<int, int>)(m => m > 0 ? m : 0))(M())));
但这有点不透明。我们如何才能进一步改进?
我们可以使它成为一个局部函数,但更好的是,我们可以使它成为一个扩展方法并进行流畅的编程:
Func<int, int> f = m => m > 0 ? m : 0;
...
N(P() ?? f(M()));
完成。这只评估public static int NotNegative(this int x) => x > 0 ? x : 0;
...
N( P() ?? M().NotNegative());
一次,但超级奖金,它更容易阅读,因为现在程序文本代表正在执行的操作,而不是程序文本是一大堆硬 - 阅读标点符号。
一些流畅的扩展方法可以使您的代码更容易阅读。养成使用它们的习惯。