我可以将using(){}块与方法';s out参数

本文关键字:方法 参数 out using 我可以 | 更新日期: 2023-09-27 18:15:22

给定一个方法

public static bool Connection.TryCreate(out Connection connection) {}

还有一段调用代码:

Connection connection;
if (!Connection.TryCreate(out connection))
    // handle failure gracefully.
/*
 * work with connection
 *
 * …
 *
 */
connection.Dispose();

我使用与bool.TryParse和friends相同的模式,即TryCreate返回操作是否成功。

我意识到using()变量在其块中需要是只读的,但有没有办法将上述内容转换为using() {}块(TryCreate只设置一次(,如下所示:

using (Connection connection)
{
    if (!Connection.TryCreate(out connection))
        // this would leave the using() block prematurely
    /*
     * work with sconnection
     *
     * …
     *
     */
}

(这不会编译:

错误CS1657:无法将"connection"作为ref或out参数传递,因为它是"using变量">

)

我可以将using(){}块与方法';s out参数

不,这是不可能的。

using (x) {...}构造在进入块时生成x的副本,因此可以执行以下操作:

var x = new FileStream(...);
using (x)
{
    x = null;
}

using块结束时,流仍将被丢弃。

必然结果是这也不会起作用:

Stream x = null;
using (x)
{
    x = new FileStream(...);
}

在这里,您在using块中构造的流将不会被处理。

然而,你能做的是:

Connection connection;
if (Connection.TryCreate(out connection))
    using (connection)
    {
    }

在C#7.0及以后的版本中,您可以将其与"out variables"组合以形成:

if (Connection.TryCreate(out var connection))
    using (connection)
    {
    }

看起来Try*模式使用不当(有些人会认为这是反模式(。

不使用TryCreate,只需使用一个Create方法,该方法在不成功的情况下抛出异常,并返回创建的连接。

然后你可以做通常的事情:

using(Connection connection = Connection.Create())
{
}

或者,如果您想避免抛出异常和所需的try{}catch{},请在无法创建连接时让Create方法返回null,并对此进行测试。

你可以这样做:

Connection connection;
if (Connection.TryCreate(out connection))
{
    using (connection)
    {
        …
    }
}

但如果你只是在失败时返回null可能会更好:

using (Connection connection = Connection.Create())
{
    if (connection != null)
    {
        …
    }
}

using创建的finally块检查connection是否为null,如果是则不执行任何操作。

此外,如果您没有在using中声明变量,那么它不必是只读的。

否。如果您担心方法调用和使用之间的异常,可以使用try/finaly:

Connection conn = null;
try {
    if(!conn.TryCreate(out conn)) return;
    ...
} finally {
    if(conn != null) conn.Dispose();
}

侧身迈出一步?

public class ConnectTo : IDisposable
{
  public Connection CurrentConnection {get; private set;}
  public ConnectTo()
  {
    CurrentConnection = null;
    // Connect up to whatever.
  }

  #region IDisposable
  // Blah blah
  #endregion
}

然后

using( ConnectedTo conn = new ConnectTo())
{
  if (conn.CurrentConnection != null)
  {
    //Do Stuff
  }
}