首页 > 编程语言 >C#中的using用法总结

C#中的using用法总结

时间:2023-06-29 13:44:14浏览次数:55  
标签:await C# global System 用法 static var using

  using一般有两个作用:

  1、作为语句,用于定义一个范围,在此范围的末尾将释放对象(IDisposable和IAsyncDisposable接口)

  2、作为指令,用于引入命名空间或者类型,或者为引入的命名空间或者类型定义别名

  using语句

  using语句应该都很熟悉了吧,从最早的ADO.net,或者对文件、流的操作,一般都会使用using语句吧。

  using(await using)语句的作用对象是实现了IDisposable(IAsyncDisposable)接口的对象,而实现IDisposable或者IAsyncDisposable接口的对象一般都是一些非托管对象,比如文件,我们在操作完非托管对象后,一般需要释放它们,而using(await using)就类似一个语法糖,它为IDisposable(IAsyncDisposable)接口的对象的提供了一个作用范围,在退出这个作用返回的时候,会自动调用Dispose(DisposeAsync)方法。

  IAsyncDisposable是IDisposable的异步形式,一个简单的使用例子:

    public static async Task Main(string[] args)
    {
        //using针对IDisposable接口对象
        using (var reader = new StreamReader("text.log"))
        {
            var text = reader.ReadToEnd();
        }
        //await using针对IAsyncDisposable接口对象
        await using (var myUnmanagedObject = new MyUnmanagedObject())
        {
            var str = myUnmanagedObject.ToString();
        }
    }
    class MyUnmanagedObject : IAsyncDisposable
    {
        public async ValueTask DisposeAsync()
        {
            await Task.CompletedTask;
            Console.WriteLine("DisposeAsync");
        }
    }

  其实using(await using)的作用等价于下面的形式:

    public static async Task Main(string[] args)
    {
        //using针对IDisposable接口对象
        var reader = new StreamReader("text.log");
        try
        {
            var text = reader.ReadToEnd();
        }
        finally
        {
            reader.Dispose();
        }
        //await using针对IAsyncDisposable接口对象
        var myUnmanagedObject = new MyUnmanagedObject();
        try
        {
            var str = myUnmanagedObject.ToString();
        }
        finally
        {
            await myUnmanagedObject.DisposeAsync();
        }
    }

  也就是说,在using(await using)的范围内,无论有没有发生错误,都会自动调用Dispose(DisposeAsync)方法。

  为了更方便的使用using(await using),我们还可以省略大括号,这意味着,using(await using)的作用区间就是从using(await using)开始至变量退出的区间,可以简单的理解为可以使用这个变量的范围区间,比如:

    public static async Task Main(string[] args)
    {
        //using针对IDisposable接口对象
        using var reader = new StreamReader("text.log");
        var text = reader.ReadToEnd();

        //await using针对IAsyncDisposable接口对象
        await using var myUnmanagedObject = new MyUnmanagedObject();
        var str = myUnmanagedObject.ToString();

        //退出方法前会自动调用Dispose或者DisposeAsync方法
        //也就是说using的范围是using开始至方法结尾
    }

   using指令

   using指令常用于引入命名空间或者类,目前(C#10)一般有4种格式:

  1、引入命名空间:using [命名空间]

  比如:  

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    namespace ClassLibrary
    {
        using System.IO;
        using System.Drawing;

        //其它代码
    }
    using的位置
    1、源代码文件的开头,位于任何命名空间或类型声明之前。
    2、如果在任何命名空间中,则必须在该命名空间中的所有命名空间和类型之前

  2、与global结合(C#10提供):global using [命名空间]

  比如:  

    global using System;
    global using System.Collections.Generic;
    global using System.Linq;
    global using System.Text;
    global using System.Threading.Tasks;

   global using和using的区别是,using只是将命名空间作用于当前的源文件,而global using就是将命名空间作用于当前项目的所有源文件,这样就不需要我们每个文件都去引入了。

  这是很好用的一个语法糖,我们可以在任何一个C#的源文件中使用global using,但是global using必须出现在文件开头,包括在那些没有global的using开头!

  :global using的作用,我们也可以通过修改csproj文件还完成:  

    <ItemGroup>
        <Using Include="System"/>
        <Using Include="System.Collections.Generic"/>
        <Using Include="System.Linq"/>
        <Using Include="System.Text"/>
        <Using Include="System.Threading.Tasks"/>
    </ItemGroup>

  3、与static结合:using static [全限定名称的类型]

  using static的作用就是将指定的类型的静态成员展开,这样我们在用的时候就不需要再写类型了,而是直接使用方法就可以了:  

    using static System.Console;

    namespace ClassLibrary
    {
        class Program
        {
            void Main(string[] args)
            {
                WriteLine("Hello World!");

                //等价于

                Console.WriteLine("Hello World!");
            }
        }
    }

   使用using static时,需要注意几点:  

    1、using static可以作用于任何类型,包括结构体、嵌套类型等,但是使用时必须使用全限定名称(命名空间+类型名成)
    2、当using static导致方法名称冲突时,需要使用通常的类型来指明,比如类中已经定义了一个WriteLine方法,那么就需要显示的用类型来指明
    3、using static只会导入自定义的静态成员,不会导入父类的静态成员

  此外,static也可以与global一起使用,表示往项目中的每个源文件都导入指定类型的静态成员,比如:  

    global using static System.Console;

    namespace ClassLibrary
    {
        class Program
        {
            void Main(string[] args)
            {
                WriteLine("Hello World!");

                //现在你可以在当前项目的其它原文件中使用Console中的静态成员了
            }
        }
    }

  :同样,我们可以通过修改csproj项目文件来实现global using static 的相关:  

    <ItemGroup>
        <Using Include="System.Console" Static="true"/>
    </ItemGroup>

  4、定义别名:using [别名]=[命名空间|类型]

  别名用于简化我们的代码,using定义的别名可以作用于命名空间,或者类型,比如:  

    namespace ClassLibrary
    {
        using s = System;
        using c = System.Console;

        class Program
        {
            void Main(string[] args)
            {
                var now = s.DateTime.Now;
                c.WriteLine("Hello World!");
            }
        }
    }

  需要注意的是,这里的using,无论是对命名空间,还是类型,都必须使用全限定名称!

  当然,using别名也可以与global结合,这里就不重复叙述了。

  

  结语

  说到using引入命名空间,不知道大家有没有考虑过这么一个问题,假如有两个dll,里面都有一个相同名称,相同命名空间的类型,如果我们同一个项目中引用这两个dll,我们怎么指定使用哪个类型?

  例如:LibraryA项目有个类Library.MyClass,LibraryB项目有个类Library.MyClass,如果我们有一个LibraryC项目同时引用了LibraryA和LibraryB,那么在LibraryC中要使用LibraryA的Library.MyClass,如果直接引用Library.MyClass,那么肯定会报错,因为程序不知道到底是LibraryA还是LibraryB。这个时候,我们需要定义一个命名来区分。

  在我们引用项目或者dll文件的依赖项中,右键依赖项=》属性,开发属性面板,有个别名的栏位,我们可以将LibraryA和LibraryB定义两个不一样的别名:

  

  此外,我们也可以通过修改csproj项目文件来添加别名:  

  <ItemGroup>
    <ProjectReference Include="..\LibraryA\LibraryA.csproj">
      <Aliases>A</Aliases>
    </ProjectReference>
    <ProjectReference Include="..\LibraryB\LibraryB.csproj">
      <Aliases>B</Aliases>
    </ProjectReference>
  </ItemGroup>

  接着在代码中使用extern alias声明一个外面的别名,就可以正常使用了:  

    extern alias A;
    extern alias B;

    namespace ClassLibrary
    {
        class Program
        {
            void Main(string[] args)
            {
                var ClassA = new A::Library.MyClass();
                var ClassB = new B::Library.MyClass();
            }
        }
    }

  此时,using别名就提供了一个很好的作用:  

    extern alias A;
    extern alias B;

    global using LibraryA = A::Library;
    global using LibraryB = B::Library;

    namespace ClassLibrary
    {
        class Program
        {
            void Main(string[] args)
            {
                var ClassA = new LibraryA.MyClass();
                var ClassB = new LibraryB.MyClass();
            }
        }
    }

  剩下的工作就交给LibraryA、LibraryB...

 

  参考文档:

  https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/using

  https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-directive

  

标签:await,C#,global,System,用法,static,var,using
From: https://www.cnblogs.com/shanfeng1000/p/16992958.html

相关文章

  • 001.SQL的@@ROWCOUNT使用
    在线演示:http://v.youku.com/v_show/id_XMzMyMTg3MzI4.html演示下载:http://115.com/file/antb46tj演示重点SQL的系统变量@@ROWCOUNT返回的是上一语句影响的行数。最早的时候,我很自然的认为这个被影响的行数应该是类似于INSERT、UPDATE、DELETE这样的语句。因为,它们很......
  • [Telerik]RadDocking第04篇 设置面板的停靠状态IsPinned
    一、演示概述此演示展示了设置每个RadPane的IsPinned属性来控制面板是否被钉住,或者缩小到隐藏区域。所谓钉住面板,其实就是将面板固定住,而不是自动缩放到隐藏区域。通过将RadPane.IsPinned设置为True可以将面板固定住,设置为false则不固定面板,将其防止在停靠区域。相关下载(屏幕......
  • 02-ES6语法:const常量
    ES6标准中增加了新的关键字const来定义常量。使用const定义的常量,在后续的代码中将无法被改变。下面是简单的屏幕分享,不爱看文字的同道中人可以看视频。-_-一、基本常量首先我们来看下如何通过这个关键字定义常量,代码如下:<script>constPI=3.14159;console.info(PI)......
  • 华为交换机链路聚合Eth-trunk LACP配置实例
    链路聚合基本概念:链路聚合是把两台设备之间的链路聚集在一块,当做一条逻辑链路使用。链路聚合的作用:1.增加链路带宽:多个链路聚合成一个带宽更大的链路,一般采用基于流的负载均衡模式;2.增加链路可靠性:通过聚合组的多个链路,若一条物理链路出现问题,不会影响整个逻辑链路聚合组链路;3.实现......
  • 大数据分析工具有哪些?详解瓴羊Quick BI
    随着大数据时代的来临,企业对数据的需求变得越来越迫切。大数据分析工具,包括数据挖掘工具、大数据处理框架、商业智能及数据可视化工具等,正成为企业管理者的得力助手。瓴羊QuickBI作为一款国产BI工具,帮助企业用户实现高效、快速、准确的企业大数据处理与分析,成为国内优秀的大数据分......
  • 深入学习 GC 算法 - 标记清除算法
    博主介绍:✌博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家✌......
  • cdr软件怎么绘制立体图?cdr绘制立体图形的教程
    CorelDRAW的简称是cdr,是一款专业的矢量图绘制软件,一般都是用来绘制二维图形的,但是也可以绘制三维图形,下面内容就来用cdr软件演示绘制三维图形的教程cdr软件绘制三维图形的教程:进入CorelDRAW的操作界面,在左侧的工具箱列表中找到“椭圆形工具”,绘制出如图1所示的一个扁状椭圆形。图1:......
  • centos8.3 openssh8.0p1升级到9.0P1代码
    #!/bin/shcd/etc/yum.repos.dmkdirbackupmvCent*backupwget-O/etc/yum.repos.d/CentOS-Base.repohttps://mirrors.aliyun.com/repo/Centos-8.repoyum-ycleanallyum-ymakecacheyum-yinstallgccgcc-c++glibcmakeautoconfopensslopenssl-deve......
  • constructive algorithms
    E.MishaandPaintingshttps://codeforces.com/problemset/problem/1720/E题意:给到一个n*n矩阵,问至少需要几次操作才能使得矩阵中有exactlyk个点。每次操作定义为选定一个方阵,将其所有元素变为x,x自定义。n<=500,k<=n2,aij<=n2题解:对于这类构造题,我们往往希望粗调逼近所需值......
  • ln -s /dev/null /root/etc/systemd/system/snapd.service
    disablesnapdduringdell-recoveryrunIt'snotneeded,thisspeedsuptherebootbetweenstagesandpreventsOOMonlowmemoryconfigsforinstaller. 这段代码用于在安装过程中禁用snapd服务,以避免在资源较小的配置上出现OOM(OutofMemory)问题。以下是代码的解......