it-swarm.cn

在C#中“使用”有什么用处

用户 kokos 通过提及using关键字回答了C#的精彩 隐藏的功能 提问。你能详细说明吗? using有什么用?

288
ubermonkey

using语句的原因是确保对象在超出范围时立即处理,并且不需要显式代码来确保发生这种情况。

中理解C#中的'using'语句,.NET CLR进行转换

using (MyResource myRes = new MyResource())
{
    myRes.DoSomething();
}

{ // Limits scope of myRes
    MyResource myRes= new MyResource();
    try
    {
        myRes.DoSomething();
    }
    finally
    {
        // Check for a null resource.
        if (myRes != null)
            // Call the object's Dispose method.
            ((IDisposable)myRes).Dispose();
    }
}
438
paulwhit

既然很多人仍然这样做:

using (System.IO.StreamReader r = new System.IO.StreamReader(""))
using (System.IO.StreamReader r2 = new System.IO.StreamReader("")) {
   //code
}

我想很多人还不知道你能做到:

using (System.IO.StreamReader r = new System.IO.StreamReader(""), r2 = new System.IO.StreamReader("")) {
   //code
}
121
BlackTigerX

这样的事情:

using (var conn = new SqlConnection("connection string"))
{
   conn.Open();

    // Execute SQL statement here on the connection you created
}

这个SqlConnection将被关闭而不需要显式调用.Close()函数,这将发生 即使抛出异常 ,也不需要try/catch/finally

95
Joel Coehoorn

使用可以用来调用IDisposable。它也可以用于别名类型。

using (SqlConnection cnn = new SqlConnection()) { /*code*/}
using f1 = System.Windows.Forms.Form;
30
MagicKat

使用,在...的意义上

using (var foo = new Bar())
{
  Baz();
}

实际上是try/finally块的简写。它相当于代码:

var foo = new Bar();
try
{
  Baz();
}
finally
{
  foo.Dispose();
}

当然,您会注意到,第一个代码段比第二个代码段更简洁,并且即使抛出异常,您也可能需要执行许多类型的事务清理。因此,我们提出了一个我们称之为Scope的类,它允许您在Dispose方法中执行任意代码。因此,例如,如果您有一个名为IsWorking的属性,您在尝试执行操作后总是想要设置为false,那么您可以这样做:

using (new Scope(() => IsWorking = false))
{
  IsWorking = true;
  MundaneYetDangerousWork();
}

您可以阅读更多关于我们的解决方案以及我们如何推导它 这里

21
David Mitchell

Microsoft文档声明 using 具有双重功能( https://msdn.Microsoft.com/en-us/library/zhdeatwt.aspx ),两者都是指令陈述。作为语句,正如在其他答案中指出的那样,关键字基本上是语法糖,用于确定处置 IDisposable object的范围。作为指令,它通常用于导入名称空间和类型。同样作为指令,您可以为名称空间和类型创建别名,如“C#5.0在果壳中:权威指南”一书中所指出的那样( http://www.Amazon.com/ 5-0-Nutshell-The-Definitive-Reference-ebook/dp/B008E6I1K8 ),Joseph和Ben Albahari。一个例子:

namespace HelloWorld
{
    using AppFunc = Func<IDictionary<DateTime, string>, List<string>>;
    public class Startup
    {
        public static AppFunc OrderEvents() 
        {
            AppFunc appFunc = (IDictionary<DateTime, string> events) =>
            {
                if ((events != null) && (events.Count > 0))
                {
                    List<string> result = events.OrderBy(ev => ev.Key)
                        .Select(ev => ev.Value)
                        .ToList();
                    return result;
                }
                throw new ArgumentException("Event dictionary is null or empty.");
            };
            return appFunc;
        }
    }
}

这是明智地采用的东西,因为滥用这种做法会损害一个人的代码的清晰度。在DotNetPearls( http://www.dotnetperls.com/using-alias )中,对C#别名有一个很好的解释,也提到了优点和缺点。

10
Aureliano Buendia

我过去经常使用它来处理输入和输出流。你可以很好地嵌套它们,它会消除你经常遇到的许多潜在问题(通过自动调用dispose)。例如:

        using (FileStream fs = new FileStream("c:\file.txt", FileMode.Open))
        {
            using (BufferedStream bs = new BufferedStream(fs))
            {
                using (System.IO.StreamReader sr = new StreamReader(bs))
                {
                    string output = sr.ReadToEnd();
                }
            }
        }
10
Sam Schutte

只是添加一些我感到惊讶的东西没有出现。使用(在我看来)最有趣的特点是,无论你如何退出使用块,它总是会处置对象。这包括退货和例外。

using (var db = new DbContext())
{
    if(db.State == State.Closed) throw new Exception("Database connection is closed.");
    return db.Something.ToList();
}

抛出异常或返回列表无关紧要。将始终处理DbContext对象。

8
Pluc

使用的另一个重要用途是在实例化模态对话框时。

Using frm as new Form1

Form1.ShowDialog

' do stuff here

End Using
6
Lucas

总之,当你使用一个实现IDisposable always 的类型的局部变量时,无异常,使用using1

如果你使用非局部IDisposable变量,那么 always 实现 IDisposable模式

两个简单的规则,也不例外1。否则,防止资源泄漏是* ss的真正痛苦。


1):唯一的例外是 - 当您处理异常时。那么在Dispose块中显式调用finally可能会少一些代码。

5
Konrad Rudolph

您可以通过以下示例使用别名命名空间:

using LegacyEntities = CompanyFoo.CoreLib.x86.VBComponents.CompanyObjects;

这被称为a 使用别名指令 如您所见,它可用于隐藏冗长的引用,如果您想在您的代码中明确指出您所指的内容,例如.

LegacyEntities.Account

代替

CompanyFoo.CoreLib.x86.VBComponents.CompanyObjects.Account

或者干脆

Account   // It is not obvious this is a legacy entity
4
VictorySaber

有趣的是,您还可以将using/IDisposable模式用于其他有趣的事情(例如Rhino Mocks使用它的另一个方面)。基本上,您可以利用编译器将 always call .Dispose对“used”对象这一事实。如果你有某些东西需要在某个操作之后发生......那些有明确开始和结束的东西......那么你可以简单地创建一个IDisposable类来在构造函数中启动操作,然后在Dispose方法中完成。

这允许您使用非常好的using语法来表示所述操作的显式开始和结束。这也是System.Transactions的工作原理。

4
Joel Martinez
public class ClassA:IDisposable

{
   #region IDisposable Members        
    public void Dispose()
    {            
        GC.SuppressFinalize(this);
    }
    #endregion
}

public void fn_Data()

    {
     using (ClassA ObjectName = new ClassA())
            {
                //use objectName 
            }
    }
3
Shiraj Momin

使用ADO.NET时,您可以使用关键字来处理连接对象或读取器对象。这样,当代码块完成时,它将自动处理您的连接。

3
Joseph Daigle

“using”也可用于解决名称空间冲突。请参阅 http://www.davidarno.org/c-howtos/aliases-overcoming-name-conflicts/ 我在这个主题上写的简短教程。

3
David Arno

Using语句告诉.NET在不再需要时释放using块中指定的对象。所以你应该对需要清理它们的类使用'using'块,比如System.IO Types。

1
deepak samantaray

在C#中使用关键字有两种用法,如下所示。

  1. 作为指令

通常我们使用using关键字在代码隐藏和类文件中添加名称空间。然后,它使当前页面中的所有类,接口和抽象类及其方法和属性可用。

例如:

using System.IO;  
  1. 作为声明

这是在C#中使用using关键字的另一种方法。它在提高垃圾收集性能方面起着至关重要的作用。 using语句确保即使在创建对象和调用方法,属性等时发生异常,也会调用Dispose()。 Dispose()是一种存在于IDisposable接口中的方法,有助于实现自定义垃圾收集。换句话说,如果我正在进行一些数据库操作(插入,更新,删除)但不知何故发生异常,那么using语句会自动关闭连接。无需显式调用连接Close()方法。

另一个重要因素是它有助于连接池。 .NET中的连接池有助于多次消除数据库连接的关闭。它将连接对象发送到池以供将来使用(下一次数据库调用)。下次从应用程序调用数据库连接时,连接池将获取池中可用的对象。因此,它有助于提高应用程序的性能。因此,当我们使用using语句时,控制器会自动将对象发送到连接池,因此无需显式调用Close()和Dispose()方法。

你可以使用try-catch块和using语句执行的操作相同,并显式调用finally块中的Dispose()。但using语句会自动调用以使代码更清晰,更优雅。在using块中,该对象是只读的,不能修改或重新分配。

例如:

    string connString = "Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Northwind;";  

using (SqlConnection conn = new SqlConnection(connString))  
{  
      SqlCommand cmd = conn.CreateCommand();  
      cmd.CommandText = "SELECT CustomerId, CompanyName FROM Customers";  
      conn.Open();  
      using (SqlDataReader dr = cmd.ExecuteReader())  
      {  
         while (dr.Read())  
         Console.WriteLine("{0}\t{1}", dr.GetString(0), dr.GetString(1));  
      }  
}  

在前面的代码中,我没有关闭任何连接,它将自动关闭。 using语句将由于using语句(使用(SqlConnection conn = new SqlConnection(connString))而自动调用conn.Close(),对于SqlDataReader对象也是如此。如果发生任何异常,它将自动关闭连接。

欲了解更多信息 - > https://www.c-sharpcorner.com/UploadFile/manas1/usage-and-importance-of-using-in-C-Sharp472/

1
Chamila Maddumage

对我来说,名称“使用”有点令人困惑,因为它可以是导入命名空间或语句(如此处讨论的那样)的指令,用于错误处理。

错误处理的另一个名称一直很好,也许是一个更明显的名称。

1
Seb

它也可以用于创建示例的范围:

class LoggerScope:IDisposable {
   static ThreadLocal<LoggerScope> threadScope = 
        new ThreadLocal<LoggerScope>();
   private LoggerScope previous;

   public static LoggerScope Current=> threadScope.Value;

   public bool WithTime{get;}

   public LoggerScope(bool withTime){
       previous = threadScope.Value;
       threadScope.Value = this;
       WithTime=withTime;
   }

   public void Dispose(){
       threadScope.Value = previous;
   }
}


class Program {
   public static void Main(params string[] args){
       new Program().Run();
   }

   public void Run(){
      log("something happend!");
      using(new LoggerScope(false)){
          log("the quick brown fox jumps over the lazy dog!");
          using(new LoggerScope(true)){
              log("nested scope!");
          }
      }
   }

   void log(string message){
      if(LoggerScope.Current!=null){
          Console.WriteLine(message);
          if(LoggerScope.Current.WithTime){
             Console.WriteLine(DateTime.Now);
          }
      }
   }

}
1
Siamand Maroufi

并不是说它非常重要,但使用它也可以用来动态改变资源。如前所述,是可丢弃的,但也许具体地说,您不希望在执行的其余部分中它们与其他资源不匹配的资源。因此,您希望将其丢弃,以免干扰其他地方。

1
Scot McPherson

Rhino Mocks记录播放语法 有趣地使用using

1
Gilligan

Using语句提供了一种方便的机制来正确使用IDisposable对象。通常,当您使用IDisposable对象时,您应该在using语句中声明并实例化它。 using语句以正确的方式调用对象上的Dispose方法,并且(如前所示使用它时)一旦调用Dispose,它也会导致对象本身超出范围。在using块中,该对象是只读的,不能修改或重新分配。

这来自: 这里

1
snowell

感谢下面的评论,我会稍微清理一下这篇文章(当时我不应该使用'垃圾收集'这个词,道歉):
使用时,它将在使用范围的末尾调用对象上的Dispose()方法。因此,您可以在Dispose()方法中获得相当多的清理代码。
这里的一个要点有望得到这个非标记:如果你实现IDisposable,请确保你在Dispose()实现中调用GC.SuppressFinalize(),否则自动垃圾收集会尝试出现并在某个时刻完成它,如果你已经Dispose()d,那至少会浪费资源。

1
Grank

大括号外的所有东西都被处理掉了,所以如果不使用它们,最好处置它们。这是因为如果您有一个SqlDataAdapter对象,并且您在应用程序生命周期中只使用它一次并且您只填充一个数据集而您不再需要它,则可以使用以下代码:

using(SqlDataAdapter adapter_object = new SqlDataAdapter(sql_command_parameter))
{
   // do stuff
} // here adapter_object is disposed automatically
1
milot

Using关键字定义对象的范围,然后在范围完成时处理对象。例如。

using (Font font2 = new Font("Arial", 10.0f))
{
    // use font2
}

请参阅 此处 有关C#使用关键字的MSDN文章。

1
David Basarab

另一个合理使用的示例,其中立即处理对象:

using (IDataReader myReader = DataFunctions.ExecuteReader(CommandType.Text, sql.ToString(), dp.Parameters, myConnectionString)) 
{
    while (myReader.Read()) 
    {
        MyObject theObject = new MyObject();
        theObject.PublicProperty = myReader.GetString(0);
        myCollection.Add(theObject);
    }
}
1
Brendan Kendrick

使用 用于在使用后需要处理的资源时使用。

例如,如果您分配一个文件资源并且只需要在一段代码中使用它来进行一些读取或写入,则使用有助于在完成后立即处理文件资源。

正在使用的资源需要实现IDisposable才能正常工作。

例:

using (File file = new File (parameters))
{
    *code to do stuff with the file*
}
1
Bob Wintemberg