首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

C# using 關鍵字三大用法完全指南:指令、別名、陳述式

     編輯:ASP.NET 基礎

前言

C# 中的 using 關鍵字有三種截然不同的用法,分別作用於命名空間匯入、型別別名、資源釋放區塊。許多開發者只熟悉前兩種,忽略 using statement 的資源管理威力。本文將三大用法一次釐清,並提供進階模式與最佳實務。

三大用法速查表

用法 語法位置 目的 關鍵字角色
using 指令 檔案頂端 / 命名空間區塊 匯入命名空間,簡化型別名稱 指令
using 別名 檔案頂端 / 命名空間區塊 為型別/命名空間建立短名稱,解決名稱衝突 指令 + =
using 陳述式 方法區塊內 確保 IDisposable 物件離開區塊時自動 Dispose() 陳述式

用法一:using 指令

基本語法

using System;
using System.Collections.Generic;
using System.Linq;

進階:using static (C# 6+)

using static System.Console;
using static System.Math;

// 直接呼叫靜態成員
WriteLine(Sqrt(2)); // 等同 Console.WriteLine(Math.Sqrt(2))

進階:global using (C# 10+ / .NET 6+)


// GlobalUsings.cs (專案層級,通常由 SDK 隱含產生)
global using System;
global using System.Collections.Generic;
// 專案所有檔案自動可用,無需每檔重複寫

用法二:using 別名

解決型別名稱衝突


// 兩個命名空間都有 MyClass
using Alias1 = NameSpace1.MyClass;
using Alias2 = NameSpace2.MyClass;

// 使用時明確指定
var obj1 = new Alias1();
var obj2 = new Alias2();

為泛型型別建立簡短別名


using StringList = System.Collections.Generic.List<string>;
using IntDict = System.Collections.Generic.Dictionary<int, string>;

var names = new StringList { "A", "B" };
var map = new IntDict { [1] = "One" };

為命名空間建立別名


using Net = System.Net;
using NetHttp = System.Net.Http;

var client = new NetHttp.HttpClient();

注意事項

  • 別名僅在宣告的檔案/命名空間區塊有效。
  • 若兩個衝突型別都需使用,**兩者都必須建立別名**;單獨為其中一個建立別名,另一個仍需完整名稱。
  • 別名不可用於 typeof、nameof、屬性標記等語法位置。

用法三:using 陳述式

核心機制


// 語法糖:編譯器展開為 try/finally
using (var resource = new Resource())
{
    resource.DoWork();
}
// 等價於
Resource resource = new Resource();
try
{
    resource.DoWork();
}
finally
{
    if (resource != null) resource.Dispose();
}

多重資源巢狀寫法 (C# 8+ 推薦)


// 傳統巢狀
using (var fs = File.OpenRead("a.txt"))
using (var sr = new StreamReader(fs))
using (var sw = new StreamWriter("b.txt"))
{
    // ...
}

// C# 8+ 簡潔語法(無大括號,區塊結束自動 Dispose)
using var fs = File.OpenRead("a.txt");
using var sr = new StreamReader(fs);
using var sw = new StreamWriter("b.txt");
// 方法結束時依宣告順序反向 Dispose

進階:自訂 Dispose 行為


public class TransactionScope : IDisposable
{
    private bool _completed;
    public void Complete() => _completed = true;
    
    public void Dispose()
    {
        if (!_completed) Rollback();
        else Commit();
    }
}

// 使用
using (var tx = new TransactionScope())
{
    DoWork();
    tx.Complete(); // 標記成功,Dispose 時 Commit
}

實務最佳實務

1. 檔案結構標準化


// 1. global using (專案層級,隱含)
// 2. 檔案層級 using 指令
using System;
using System.Threading.Tasks;

// 3. using 別名(僅在衝突或簡化泛型時)
using Config = MyApp.Configuration.Settings;

// 4. using static(僅極常用靜態類別)
using static System.Console;

2. 資源管理鐵律

  • 所有實作 IDisposable 的物件,必須在 using 區塊中建立並使用(Stream、DbConnection、HttpClient、GDI+ 物件、COM 物件等)。
  • 不要在 using 區塊外呼叫 Dispose() 再進入區塊(雙重 Dispose 可能拋出例外)。
  • 非同步資源:await using (C# 8+) 配合 IAsyncDisposable。

3. 避免常見錯誤


// ❌ 錯誤:物件在 using 區塊外建立
var conn = new SqlConnection(cs);
using (conn) { ... } // 若這裡拋出例外,外層 conn 可能未 Dispose

// ✅ 正確:在 using 內建立
using (var conn = new SqlConnection(cs)) { ... }

// ❌ 錯誤:using 區塊內重新指派變數
using (var fs = File.OpenRead("a.txt"))
{
    fs = File.OpenRead("b.txt"); // 原本的 fs 失去參考,無法 Dispose!
}

// ✅ 正確:分開宣告
using var fs1 = File.OpenRead("a.txt");
using var fs2 = File.OpenRead("b.txt");

完整範例程式


using System;
using System.IO;
using System.Data.SqlClient;
// using 別名解決泛型冗長
using UserMap = System.Collections.Generic.Dictionary<int, string>;

namespace UsingDemo
{
    class Program
    {
        static void Main()
        {
            // using 陳述式管理多重資源
            using (var conn = new SqlConnection("Data Source=.;Initial Catalog=Test;Integrated Security=True"))
            using (var cmd = conn.CreateCommand())
            {
                conn.Open();
                cmd.CommandText = "SELECT Id, Name FROM Users";
                using (var reader = cmd.ExecuteReader())
                {
                    var users = new UserMap();
                    while (reader.Read())
                    {
                        users[reader.GetInt32(0)] = reader.GetString(1);
                    }
                    // 顯示結果
                    foreach (var kv in users)
                        Console.WriteLine($"{kv.Key}: {kv.Value}");
                }
            } // 依序 Dispose reader, cmd, conn

            // C# 8+ using var
            using var fs = File.CreateText("log.txt");
            fs.WriteLine("Done");
        }
    }
}

總結

  • using 指令:匯入命名空間,配合 global using、using static 簡化專案結構。
  • using 別名:解決型別名稱衝突、簡化泛型閉合型別、縮短長命名空間。**衝突雙方都要建立別名**。
  • using 陳述式:資源管理核心,確保 IDisposable 物件確定性釋放。C# 8+ using var、await using 更簡潔安全。
  • 三者語意完全無關,唯一共通點是關鍵字 using。閱讀程式碼時務必依語境區分。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved