干(不要重复自己)和如果分配

Pho*_*que 1 c# syntax if-statement dry

我想我忘记了一些明显的东西,但是我似乎无法找到一种方法来分配一个值,如果它确认一个条件尽可能保持DRY ......一些代码来解释我的意思......

a = (b > 1) ? b : c;
Run Code Online (Sandbox Code Playgroud)

甚至 a = (a > 1) ? a : b;

所以当然这里没什么大不了的,但如果要用方法调用替换,(可能是那里的收益率)或其他什么,那么我就要调用它两次......

我唯一看到的是将它存放在一个变量中,然后就像上面的代码一样......

有什么好主意吗?

编辑以便更好地理解:假设我在xml文件中搜索一个值,使用空检查(?.?[])等等

string store_no = myXmlNode.SelectSingleNode("aChildNode")?.SelectSingleNode("myNode")?.Attributes?["store_no]?.Value;
Run Code Online (Sandbox Code Playgroud)

所以在这里我将它存储在一个变量中,以便我可以稍后测试它的值.如果我想检查一个特定的store_no!我将不得不做类似的事情

store_no = (store_no=="STORE23")? store_no : "unknown";
Run Code Online (Sandbox Code Playgroud)

...是的,不确定这个例子是否足够明确,但这个想法就在这里; 我可能不想将数据存储在变量(例如巨大的数据块)中是否有办法获得相同的结果?

Eri*_*ert 8

我想我忘记了一些明显的事情,但如果它确认一个条件尽可能保持DRY,我似乎找不到分配值的方法

让我们首先解除你对常见的误解.

这完全是对DRY含义的误解.如果你有一个Customer对象,你有一个Address对象,Customer具有领域BillingCityBillingPostalCodeHomeCity等,则是因为相同的信息在两个地方代表的冗余代码是不干燥.您应该重新设计代码,以便a Customer具有一组Address对象.

现在,避免在整个节目中剪切和粘贴重复代码确实是一个好主意,但DRY是关于中到大规模的代码设计.DRY绝对不意味着你的代码不应该在同一个表达式中两次使用相同的变量!

现在我们已经解决了这个问题,让我们来看看你对语言的批评.

我们经常处于一种"表达背景"的情况 - 即一种长期的,可能流畅的表达方式,我们希望避免做多余的工作.例如,我们可能有:

x = M() > 0 ? M() : 0;
Run Code Online (Sandbox Code Playgroud)

也许M()两次打电话很贵,或者说它不是幂等的.随你.无所谓.重点是,我们不想把它叫两次.

令人恼火的是,我们必须退出表达式上下文并进入语句上下文:

var m = M();
x = m > 0 ? m : 0;
Run Code Online (Sandbox Code Playgroud)

这当然是合法的,但有点令人烦恼.此外,在某些情况下,它可能很棘手:

N(P() ?? (M() > 0 ? M() : 0));
Run Code Online (Sandbox Code Playgroud)

现在我们做什么?没有明显的方法来保留语义而不用长手写出来,假设我们只想调用M()if P()为null.

var t = default(T);
var p = P();
if (p == null) {
  var m = M();
  t = m > 0 ? m : 0;
} else  {
  t = p.Value;
}
N(t);
Run Code Online (Sandbox Code Playgroud)

YUCK.天哪,这太可怕了.

其他语言通过引入let表达式来解决这个问题 我们真正想要的是能够在表达式的中间引入一个新的局部.常见的语法是let ID = EXPRESSION in EXPRESSION并且ID成为具有特定含义的只读变量,但仅在以下范围内in:

N(P() ?? (let m = M() in m > 0 ? m : 0));
Run Code Online (Sandbox Code Playgroud)

需要注意的是C#支持let表达式,但只有在查询理解.如果它在语言中更普遍地支持它会很棒.

多年来,有许多建议将let表达式或其更一般的形式,顺序表达式添加到C#中多年来.有关示例,请参阅github roslyn问题跟踪器.也许这会进入C#8; 如果你想要它,去参加论坛.

那么你能做些什么呢?

事实证明在C#中 let-expression. let x = y in z只是一种很好的写作方式(((Func<X, Z>)(x=>z))(y)).所以你可以写:

N(P() ?? (((Func<int, int>)(m => m > 0 ? m : 0))(M())));
Run Code Online (Sandbox Code Playgroud)

但这看起来几乎是可怕的.这是一个难以理解的混乱.

问题是lambda.这会更好:

Func<int, int> f = m => m > 0 ? m : 0;
...
N(P() ?? f(M()));
Run Code Online (Sandbox Code Playgroud)

但那有点不透明.我们如何才能进一步改进?

我们可以使它成为一个局部函数,但更好的是,我们可以使它成为一个扩展方法并进行流畅的编程:

public static int NotNegative(this int x) => x > 0 ? x : 0;
...
N( P() ?? M().NotNegative());
Run Code Online (Sandbox Code Playgroud)

完成.这只评估M()一次,但超级奖金,它更容易阅读,因为现在程序文本代表正在执行的操作,而不是程序文本是一大堆难以阅读的标点符号.

一些流畅的扩展方法可以使您的代码更容易阅读.养成使用它们的习惯.