C#条件使用块语句

我有以下代码,但它很尴尬。 我怎么能更好地构建它? 我是否必须使我的消费类实现IDisposable并有条件地构建网络访问类并在完成后处置它?

protected void ValidateExportDirectoryExists() { if (useNetworkAccess) { using (new Core.NetworkAccess(username, password, domain)) { CheckExportDirectoryExists(); } } else { CheckExportDirectoryExists(); } } 

基于C#编译器仅在资源为非null时才调用Dispose这一事实,有一种选择,有点令人讨厌但可行。

 protected void ValidateExportDirectoryExists() { using (useNetworkAccess ? new Core.NetworkAccess(username, password, domain) : null) { CheckExportDirectoryExists(); } } 

另一种方法是编写一个返回null或NetworkAccess的静态方法:

 private Core.NetworkAccess CreateNetworkAccessIfNecessary() { return useNetworkAccess ? new Core.NetworkAccess(username, password, domain)) : null; } 

然后:

 protected void ValidateExportDirectoryExists() { using (CreateNetworkAccessIfNecessary()) { CheckExportDirectoryExists(); } } 

再说一次,我仍然不确定我不喜欢原版……这实际上取决于你需要这种模式的频率。

如果您在许多方法中重复此模式,您可以打破模式

 protected void OptionalNetworkCall(Action action) { if (useNetworkAccess) { using (new Core.NetworkAccess(username, password, domain)) { action(); } } else { action(); } } protected void ValidateExportDirectoryExists() { OptionalNetworkCall(CheckExportDirectoryExists); } 

using语句是避免“finally”块的快捷方式,只应在代码更容易理解时使用。 在你的情况下,我会写下面的代码。 它可能不像其他一些版本那么简短,但更直接。

 protected void ValidateExportDirectoryExists() { Core.NetworkAccess access = useNetworkAccess ? new Core.NetworkAccess(username, password, domain) : null; try { CheckExportDirectoryExists() } finally { if (access != null) { access.Dispose(); } } } 
 protected void ValidateExportDirectoryExists() { var access = useNetworkAccess ? new Core.NetworkAccess(username, password, domain) : null; using (access) { CheckExportDirectoryExists(); } } 

我不知道它是否“更好”,但您可以使用空对象模式并具有“空”一次性网络访问对象。 像这样的东西:

 protected void ValidateExportDirectoryExists() { using (GetNetworkAccess(username, password, domain)) { CheckExportDirectoryExists(); } } protected IDisposable GetNetworkAccess(string username, string password, string domain) { return useNetworkAccess ? new Core.NetworkAccess(username, password, domain) : new NullNetworkAccess(username, password, domain); } internal class NullNetworkAccess : IDisposable { internal NullNetworkAccess(string username, string password, string domain) { } public void Dispose() { } } 

这对他们自己的好处来说可能太可爱了。

[编辑]刚才在Jon的回答中看到null可以在using语句中使用。 我不知道!

如果类实现了IDisposible接口,则使用scope只会处理一个对象,所以是的,你需要实现dispose方法。

我想这真的是化妆品的问题,如果代码就这么简单。

我可以想象它是如何看待另一种方式的,我的投票将是你现在拥有的这个版本。

无论在using语句中包含什么,它IDispoable.DisposeIDispoable.Dispose调用,由IDisposable接口指定。 正如在MSDN上看到的那样……

提供方便的语法,确保正确使用IDisposable对象。

因此,如果在using语句中放置自定义类型,它应该通过IDisposable接口适当地清理其资源。

通过让您的类实现IDisposable,只有在使用“using”语句时才会调用dispose方法。 否则你必须明确地调用dispose。

通常,IDisposable由管理垃圾收集器之外的内存消耗的对象实现(例如,使用非托管代码)。 它提供了一种清理任何消耗内存的方法。

只要您的NetworkAccess类实现了IDisposable,就会在using语句的作用域完成后立即调用dispose方法。 如果是托管代码,则无需处理它。 让垃圾收集器完成它的工作。

使用您自己的try / finally块,它执行与’using’类似的逻辑,但只有在设置了useNetworkAccess时才执行dispose。 请注意,如果useNetworkAccess可能受到其他线程的影响,则应复制其值并使用该副本创建资源并进行处置。