堆叠使用语句与单独使用语句
Stacked using statements vs seperate using statements
在重构代码时,我偶然发现了一些堆叠的 using 语句(我说的是 10 到 15 条左右)。
using(X x=new X())
using(Y y=new Y())
using(Z z=new Z())
using(...)
{
List<X> listX= x.GetParameterListByID(pID);
List<Y> listY=y.GetParameterListByID(pID);
...
...
//other (business) calls/code, like 20-30 lines, that don't need the using instances
}
Class 示例类似于
public class X : IDisposable{
public List<XParameterInfo> GetParameterListByID(int? pID){
const string query="SELECT name,value FROM parameters WHERE id=@ID";
//query code here
return queryResult;
}
}
我想到的第一件事是,知道 using
基本上是 try{} finally{ x.Dispose(); }
,使用连接将保持 open/active 直到使用块中的代码完成时只需要填写一个列表。
以上是我的推测,如有错误请指正。
考虑到我说的是正确的,写一些像
这样的东西会更好吗(性能,但主要是好的实践)
List<X> listX;
List<Y> listY;
List<Z> listZ;
...
//for the example here I wrote out 3 but let's talk 10 or more
using(X x=new X())
{
listX=x.GetParameterListByID(pID);
}
using(Y y=new Y())
{
listY=y.GetParameterListByID(pID);
}
using(Z z=new Z())
{
listZ=z.GetParameterListByID(pID);
}
...
// other calls but now outside the using statements
或者它可以忽略不计,除了堆叠的 using
语句带走了嵌套代码的外观之外?
would it be better (performance wise)
这取决于使用中使用的类型。你不能做笼统的陈述。
性能不是唯一因素,打开资源可能会阻塞其他进程或导致内存问题。但另一方面,更紧凑的第一个版本增加了可读性。因此,您必须确定是否存在问题。如果没有,为什么要打扰?然后选择可读性和可维护性最好的代码。
但是你可以重构你的代码,使用一个方法来封装使用:
// in class X:
public static List<X> GetParameterListByID(int pID)
{
using(X x = new X())
{
return x.GetParameterListByID(pID);
}
}
// and same in other classes
现在代码没有用处了:
List<X> listX = X.GetParameterListByID(pID); // static method called
List<Y> listY = Y.GetParameterListByID(pID); // static method called
除了 Tim 所说的,许多数据库驱动程序使用 "Connection Pooling" 通过重用旧连接来提高连接性能。因此,当 Dispose
在连接上被调用时,它们并没有真正关闭(除非满足某些条件),但它们会保持空闲状态以供后续调用。
https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/connection-pooling
为什么不对所有查询使用 1 个连接?
我认为这将是一个更优雅的解决方案。
void Main()
{
List<X> listX;
List<Y> listY;
List<Z> listZ;
using(SqlConnection conn = new SqlConnection())
{
conn.Open();
listX=new X().GetParameterListByID(conn, pID);
listY=new Y().GetParameterListByID(conn, pID);
listZ=new Z().GetParameterListByID(conn, pID);
}
}
在重构代码时,我偶然发现了一些堆叠的 using 语句(我说的是 10 到 15 条左右)。
using(X x=new X())
using(Y y=new Y())
using(Z z=new Z())
using(...)
{
List<X> listX= x.GetParameterListByID(pID);
List<Y> listY=y.GetParameterListByID(pID);
...
...
//other (business) calls/code, like 20-30 lines, that don't need the using instances
}
Class 示例类似于
public class X : IDisposable{
public List<XParameterInfo> GetParameterListByID(int? pID){
const string query="SELECT name,value FROM parameters WHERE id=@ID";
//query code here
return queryResult;
}
}
我想到的第一件事是,知道 using
基本上是 try{} finally{ x.Dispose(); }
,使用连接将保持 open/active 直到使用块中的代码完成时只需要填写一个列表。
以上是我的推测,如有错误请指正。 考虑到我说的是正确的,写一些像
这样的东西会更好吗(性能,但主要是好的实践)List<X> listX;
List<Y> listY;
List<Z> listZ;
...
//for the example here I wrote out 3 but let's talk 10 or more
using(X x=new X())
{
listX=x.GetParameterListByID(pID);
}
using(Y y=new Y())
{
listY=y.GetParameterListByID(pID);
}
using(Z z=new Z())
{
listZ=z.GetParameterListByID(pID);
}
...
// other calls but now outside the using statements
或者它可以忽略不计,除了堆叠的 using
语句带走了嵌套代码的外观之外?
would it be better (performance wise)
这取决于使用中使用的类型。你不能做笼统的陈述。
性能不是唯一因素,打开资源可能会阻塞其他进程或导致内存问题。但另一方面,更紧凑的第一个版本增加了可读性。因此,您必须确定是否存在问题。如果没有,为什么要打扰?然后选择可读性和可维护性最好的代码。
但是你可以重构你的代码,使用一个方法来封装使用:
// in class X:
public static List<X> GetParameterListByID(int pID)
{
using(X x = new X())
{
return x.GetParameterListByID(pID);
}
}
// and same in other classes
现在代码没有用处了:
List<X> listX = X.GetParameterListByID(pID); // static method called
List<Y> listY = Y.GetParameterListByID(pID); // static method called
除了 Tim 所说的,许多数据库驱动程序使用 "Connection Pooling" 通过重用旧连接来提高连接性能。因此,当 Dispose
在连接上被调用时,它们并没有真正关闭(除非满足某些条件),但它们会保持空闲状态以供后续调用。
https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/connection-pooling
为什么不对所有查询使用 1 个连接?
我认为这将是一个更优雅的解决方案。
void Main()
{
List<X> listX;
List<Y> listY;
List<Z> listZ;
using(SqlConnection conn = new SqlConnection())
{
conn.Open();
listX=new X().GetParameterListByID(conn, pID);
listY=new Y().GetParameterListByID(conn, pID);
listZ=new Z().GetParameterListByID(conn, pID);
}
}