我喜欢在using块中实例化我的WCF服务客户端,因为它几乎是使用实现的资源的标准方法IDisposable:
using (var client = new SomeWCFServiceClient())
{
//Do something with the client
}
Run Code Online (Sandbox Code Playgroud)
但是,正如本MSDN文章中所述,在using块中包装WCF客户端可能会掩盖导致客户端处于故障状态的任何错误(如超时或通信问题).简而言之,当调用Dispose()时,客户端的Close()方法会触发,但会因为处于故障状态而抛出错误.然后,第二个异常掩盖了原始异常.不好.
MSDN文章中建议的解决方法是完全避免使用using块,而是实例化您的客户端并使用它们,如下所示:
try
{
...
client.Close();
}
catch (CommunicationException e)
{
...
client.Abort();
}
catch (TimeoutException e)
{
...
client.Abort();
}
catch (Exception e)
{
...
client.Abort();
throw;
}
Run Code Online (Sandbox Code Playgroud)
与using块相比,我认为这很难看.每次需要客户端时都需要编写很多代码.
幸运的是,我发现了一些其他的解决方法,例如IServiceOriented上的这个.你从:
public delegate void UseServiceDelegate<T>(T proxy);
public static class Service<T>
{
public static ChannelFactory<T> _channelFactory = new ChannelFactory<T>("");
public static void Use(UseServiceDelegate<T> codeBlock)
{ …Run Code Online (Sandbox Code Playgroud) .NET Framework 4.5中的System.Net.Http.HttpClient和System.Net.Http.HttpClientHandler实现了IDisposable(通过System.Net.Http.HttpMessageInvoker).
该using声明文件说:
通常,当您使用IDisposable对象时,您应该在using语句中声明并实例化它.
这个答案使用了这种模式:
var baseAddress = new Uri("http://example.com");
var cookieContainer = new CookieContainer();
using (var handler = new HttpClientHandler() { CookieContainer = cookieContainer })
using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
{
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("foo", "bar"),
new KeyValuePair<string, string>("baz", "bazinga"),
});
cookieContainer.Add(baseAddress, new Cookie("CookieName", "cookie_value"));
var result = client.PostAsync("/test", content).Result;
result.EnsureSuccessStatusCode();
}
Run Code Online (Sandbox Code Playgroud)
但是微软最明显的例子并没有Dispose()明确地或隐含地调用.例如:
我正在做一个项目.我必须比较两个文件的内容,看看它们是否精确匹配.
在进行大量错误检查和验证之前,我的初稿是:
DirectoryInfo di = new DirectoryInfo(Environment.CurrentDirectory + "\\TestArea\\");
FileInfo[] files = di.GetFiles(filename + ".*");
FileInfo outputFile = files.Where(f => f.Extension == ".out").Single<FileInfo>();
FileInfo expectedFile = files.Where(f => f.Extension == ".exp").Single <FileInfo>();
using (StreamReader outFile = new StreamReader(outputFile.OpenRead()))
{
using (StreamReader expFile = new StreamReader(expectedFile.OpenRead()))
{
while (!(outFile.EndOfStream || expFile.EndOfStream))
{
if (outFile.ReadLine() != expFile.ReadLine())
{
return false;
}
}
return (outFile.EndOfStream && expFile.EndOfStream);
}
}
Run Code Online (Sandbox Code Playgroud)
有嵌套using语句似乎有点奇怪.
有一个更好的方法吗?
在C#中使用块的目的是什么?它与局部变量有什么不同?
在MySQL中JOIN,ON和之间有什么区别USING()?据我所知,USING()只是更方便的语法,而ON当列名不相同时允许更多的灵活性.然而,这种差异是如此微小,你会认为他们只是消失了USING().
除此之外还有更多的东西吗?如果是,我应该在特定情况下使用哪个?
例如,我很少需要:
using System.Text;
Run Code Online (Sandbox Code Playgroud)
但它默认始终存在.我假设如果您的代码包含不必要的using指令,应用程序将使用更多内存.但还有什么我应该知道的吗?
另外,如果只在一个文件和大多数/所有文件中使用相同的using指令,它会有什么不同吗?
编辑:请注意,这个问题与被称为using语句的无关概念无关,旨在通过确保当对象超出范围时调用其IDisposable.Dispose方法来帮助管理资源.请参阅C#中"使用"的使用.
DataSet和DataTable都实现了IDisposable,因此,通过传统的最佳实践,我应该调用它们的Dispose()方法.
但是,从我到目前为止所读到的,DataSet和DataTable实际上并没有任何非托管资源,因此Dispose()实际上并没有做太多.
另外,我不能只使用,using(DataSet myDataSet...)因为DataSet有一组DataTables.
所以,为了安全起见,我需要遍历myDataSet.Tables,处理每个DataTable,然后处理DataSet.
那么,在我的所有DataSet和DataTables上调用Dispose()是否值得麻烦?
附录:
对于那些认为应该处理DataSet的人:通常,处理的模式是使用usingor try..finally,因为你想保证将调用Dispose().
然而,这对于一个集合来说真的很快.例如,如果对Dispose()的一个调用抛出异常,你会怎么做?你吞下它(这是"坏"),以便你可以继续处理下一个元素?
或者,你是否建议我只调用myDataSet.Dispose(),而忘记在myDataSet.Tables中处理DataTables?
using在(可能)null对象上使用该语句是否安全?
请考虑以下示例:
class Test {
IDisposable GetObject(string name) {
// returns null if not found
}
void DoSomething() {
using (IDisposable x = GetObject("invalid name")) {
if (x != null) {
// etc...
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
是否保证Dispose只有在对象不为空时才会被调用,而且我不会得到一个NullReferenceException?
第一个问题:
说我有
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
string storedProc = "GetData";
SqlCommand command = new SqlCommand(storedProc, connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID));
return (byte[])command.ExecuteScalar();
}
Run Code Online (Sandbox Code Playgroud)
连接是否关闭?因为从技术上讲,我们永远不会}像return以前那样到达最后.
第二个问题:
这次我有:
try
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
int employeeID = findEmployeeID();
connection.Open();
SqlCommand command = new SqlCommand("UpdateEmployeeTable", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID));
command.CommandTimeout = 5;
command.ExecuteNonQuery();
}
}
catch (Exception) { /*Handle error*/ }
Run Code Online (Sandbox Code Playgroud)
现在,说出来try我们得到一个错误,它被抓住了.连接是否仍然关闭?因为我们再次跳过其余代码try并直接转到catch …