C#具有using
语句,专门用于IDisposable对象。据推测,using
语句中指定的任何对象都将拥有某种应该被确定性释放的资源。
然而,在我看来,编程中有许多设计具有单一,明确的开始和结束,但缺乏内在的语言支持。 using
构造提供了使用代码编辑器的内置功能的机会,至少可以清楚地自然地突出显示这种设计或操作的范围。
我想到的是经常以BeginXXX()
和EndXXX()
方法开始的那种操作,尽管有很多不同的风格,例如涉及“开始”的异步代码执行“和”加入“。
拿这个天真的例子。
webDataOperation.Start();
GetContentFromHardDrive();
webDataOperation.Join();
// Perform operation that requires data from both sources
相反,如果Start方法返回了IDisposable.Dispose
方法执行连接操作的对象,该怎么办。
using(webDataOperation.Start()) {
GetContentFromHardDrive();
}
// Perform operation that requires data from both sources
或者,更好的是,我特别想到的是:我有一个高度专业化的图形blitting的对象,并且有一个Begin()
和End()
方法(DirectX和XNA中也有一个设计) 。代替...
using(blitter.BlitOperation()) {
// Do work
}
// Use result
它似乎更自然,更具可读性,但它是不可取的,因为它使用IDisposable
接口和using
语句用于非预期目的?换句话说,这是否会与o 以非直观的方式加载运算符相同?
答案 0 :(得分:20)
这是一种完全可以接受的做法。这些被称为因子类型,Framework Design Guidelines建议这样做。
基本上,如果类型包装具有特定生命周期的操作,则使用IDisposable和using语句将成为适当的考虑因素。
我实际上也在博客上写了this specific topic here。
答案 1 :(得分:12)
我建议不要这样做;我的信念是代码是与代码的维护者有效地沟通,而不是编译器,并且应该记住维护者的理解。我尝试仅使用“使用”来处置资源,通常是非托管资源。
我是少数。大多数人似乎使用“使用”作为一般目的“我想要一些清理代码运行,即使抛出异常”机制。
我不喜欢这个,因为(1)我们已经有了一种机制,称为“try-finally”,(2)它使用了一个功能,它不是用于它的目的,以及(3)如果调用它清理代码很重要,那么为什么它在被调用时不可见?如果它很重要,那么我希望能够看到它。
答案 2 :(得分:6)
仅仅因为你可以(或者因为Phil Haack说它没关系),并不意味着你应该这样做。
基本的经验法则:如果我能阅读你的代码并了解它的作用以及你的意图,那么它是可以接受的。另一方面,如果你需要解释你做了什么,或者为什么要这样做,那么可能会让初级开发人员去维护代码。
还有许多其他模式可以通过更好的封装来实现这一目标。
底线:这种“技术”不会给你带来任何好处,只会让其他开发者感到困惑。
答案 3 :(得分:5)
这是一种常见的模式,但就个人而言,我认为没有理由滥用IDisposable,就像你可以用匿名代表和/或lambdas以更明显的方式达到同样的效果;即:
blitter.BlitOperation(delegate
{
// your code
});
答案 4 :(得分:2)
我认为你应该将IDisposable用于它的目的,而不是别的。也就是说,如果可维护性对您很重要。
答案 5 :(得分:0)
我认为这是可以接受的 - 实际上,我已经在一些项目中使用它,我希望在特定代码块的末尾触发一个动作。
Wes Deyer在他的LINQ to ASCII Art计划中使用它,他称之为一次性动作(Wes在C#编译器团队工作 - 我相信他的判断:D):
http://blogs.msdn.com/wesdyer/archive/2007/02/23/linq-to-ascii-art.aspx
class ActionDisposable: IDisposable
{
Action action;
public ActionDisposable(Action action)
{
this.action = action;
}
#region IDisposable Members
public void Dispose()
{
this.action();
}
#endregion
}
现在你可以从函数中返回它,并执行以下操作:
using(ExtendedConsoleWriter.Indent())
{
ExtendedConsoleWriter.Write("This is more indented");
}
ExtendedConsoleWriter.Write("This is less indented");