我已经用C#编程了一段时间了。我最近编写了一个例程,它发生在我身上,这是我第一次(我记得)故意使用裸代码块(即没有前面的控制流语句)。代码看起来像这样:
//...
var output = source.GetRawOutput();
{
var fooItems = FooSource.GetItems();
output = TransformA.TransformOutput(output, p =>
{
GetFooContent(p, fooItems.GetNext());
});
}
{
var barItems = BarSource.GetItems();
output = TransformB.TransformOutput(output, p =>
{
GetBarContent(p, barItems.GetNext());
});
}
return output;
我用这种方式构建代码主要是作为一个完整性检查,我不会意外地引用错误的变量(即混合barItems和fooItems)。我还发现代码更具可读性。我当然可以将代码分解为三种不同的方法,但我认为在这种情况下有点过分。
您在代码中使用裸代码块吗?为什么或为什么不呢?
答案 0 :(得分:6)
如果查看代码,那两个块非常相似。我打赌他们可以重构成一个区块。
虽然这听起来不像答案,但确实如此。我想一般来说,如果你觉得想要使用这样的大括号,那么你正在处理一种情况,通过分解另一种方法或重构各种方法可以更好地处理这种情况。
总的来说,无论如何。
具体答案 - 不,一旦我擅长OO并限制我在一个单位做多少工作,我从未想过他们可能是个好主意。
编辑:使用相似的代码,它必须相当容易重构。我会试试一个重构器。对不起,如果我的语法错误,我真的不做c#而且Java没有闭包。
output = transform(FooSource, TransformA);
output = transform(BarSource, TransformB); // I know output is overwritten, but
// it is in the askers' example as well
transform(var itmSource, var transform) {
var output=source.GetRawOutput(); // Sorry, you never said where source came from.
var items = itmSource.GetItems();
output=transform.TransformOutput(output, p =>
{
GetContent(p, items.GetNext()); // GetContent may need to be passed in
// you didn't say where those calls came from.
// See comments below
});
}
return output;
}
像这样的重构不会节省太多的输入,但是它们会显示出一些很好的模式 - 比如FooSource和TransformA之间的关系(以及可能的getContent调用) - 它们应该被存储在一个对象和该对象应该传入,或类似的东西。 (很难从这个片段中分辨出来,通常重构需要比你给出的更广泛的代码视图)
请注意,它们也会强迫您考虑GetFooContent和GetBarContent。我敢打赌你喝了一品脱啤酒,这些啤酒非常相似,以至于它们可以被分解为一个方法调用,一个变量或两个传入或两个兄弟类中的方法。
由于这种关系总是出现并且总是改进你的类中的其他代码的方式,我相信这些重构绝对是强制性的,做这种重构比任何教我真正的OO更好。
答案 1 :(得分:2)
就个人而言,我不会这样做来构建代码。这在C ++中用于控制变量的范围并调用析构函数,但是当C#被垃圾收集时,我没有看到块的功能用法。
关于可读性的结构化,我相信你的方法要么小到不需要这些东西,要么应该分解成更小的方法。
答案 2 :(得分:1)
我发现,大多数时候我很想做这件事,我最好把它重构成一个单独的方法。举个例子 - 在这种情况下,看起来你可以使用一个方法来处理具有正确参数的两个裸代码块。
重构会使其更清晰,更易于维护。
答案 3 :(得分:1)
我从不使用它们,相反,我倾向于将代码块放入较小的方法中,使用描述性的名称,这样可以使意图更清晰。
我想在你提供它的例子中添加两个块,看起来很相似它可能是你用两个方法调用替换它们的一个改变,到一个为你工作的方法:
答案 4 :(得分:0)
我用它们来包装临时变量。例如,有时需要创建一个对象,设置一些变量,将它传递给一个函数,然后处理它。
答案 5 :(得分:0)
我几乎从不使用它们,就像其他人所说的那样。有一个边缘情况可供您使用:封闭块决定了编译器将变量捕获到闭包中的具体程度。
答案 6 :(得分:0)
裸代码块有一个非常有趣的用途:管理范围。
当我想要尽可能早地从GC收集一个非一次性的变量时,我必须在完成使用后立即从范围中删除它,所以我在裸块内创建变量,使用在那里,当执行离开块时,GC将看到变量超出范围,尽快收集它。
这对仅用于方法中的一些操作的大型列表很有用。如果方法的执行时间很长,那么建议在不再使用它们时删除列表。
PS:请注意,将它们设置为null将不起作用,因为当您将其设置为null时,您将引用它,因此GC将延迟收集而不是赶紧收集。