从使用中返回声明

时间:2010-04-21 13:57:35

标签: c#-3.0

  using (IDbCommand command = new SqlCommand())
         {
             IDbDataAdapter adapter = new SqlDataAdapter();
             DataSet ds = new DataSet();
             adapter.SelectCommand = command;
             command.Connection = _dataAccess.Connection;
             command.CommandType = CommandType.StoredProcedure;
             command.CommandText = "GetProcData";
             command.Parameters.Add(new SqlParameter("@ProcID  ", procId));

            adapter.Fill(ds);
            return ds.Tables[0].AsEnumerable();
         }

这会返回一个IEnumerable DataRow问题是,由于返回在using语句中,它的属性是否会处理IDBCommand?我知道我可以很容易地重构这个,所以我在使用之外更改了DataSet的范围,但它更像是一个奇迹而不是其他任何东西。

4 个答案:

答案 0 :(得分:4)

是的,这将按预期正常工作,IDbCommand处理得当。编译器会将使用块转换为try-catch-finally,其中Dispose块中调用finally

答案 1 :(得分:2)

是的,数据库命令将被处理,到目前为止一直很好。

你可以通过IEnumerables获得麻烦。因为从IEnumerable获取项目时可能会生成,而不是在创建IEnumerable时,这就是它的本质。所以它取决于ds.Tables[0].AsEnumerable()的实现方式。 可以等待执行命令,直到获得第一个项目。这是在使用块之外的调用代码中。你会收到一个错误,因为命令已被处理掉了。

这可能不是问题,但在使用块返回IEnumerables(或lambda表达式)时应始终考虑:

using (A a = new A())
{
  return someItems.Select(x => a.Get(x));
}

访问第一项时,a已经处理完毕,您收到错误。

答案 2 :(得分:2)

正确处理IDbCommand。从using语句中返回时,您可以这样做,只要:

  1. 你要归还的东西不在使用的条款中 声明
  2. 返回的东西不是在using语句块中创建的引用。
  3. 在第一种情况下,using语句将处理你想要返回的东西,在第二种情况下,变量将超出范围。

    e.g。

    //this is fine as result is createsd outside the scope of the block. 
    bool result = false;
    using (SmtpClient mailClient = new SmtpClient())
    {
        try
        {
            mailClient.Send(...);
            result = true;
         } 
         catch(SmtpException)
         {
             result = false;
         } 
         finally 
         {
             return result;
         }
    }
    

    这里,using(){ ... }声明是我们的朋友。当我们退出块时,我们会放置SmtpClient,结果条件仍然存在供您使用。

    但是,假设我们正在编写一个WinForm应用程序或WPF应用程序,我们在数据上下文中包含一个使用块,然后我们会在控件可以使用它之前上下文消失时创建一个问题。

    // this will fail when you bind the customers to a form control!
    using (DbContext context = new DBContext())
    {
    context.Customers.Where(c => c.Name.Contains("Bob")).Load();
    return context.Customers.Local;
    }
    

    在这里,using(){ ... }声明会伤害我们。当我们将数据绑定到GridView(或其他此类数据绑定控件)时,我们处理DbContext这一事实将意味着我们的表单没有任何内容可以绑定,因此它会抛出异常!

    HTH

答案 3 :(得分:0)

IDbCommand对象的范围非常明确:括号{}之间。一旦程序流从那里退出,对象就会被处理掉。