0. 目录

C#6 新增特性目录

1. 老版本的代码

 1 using System;
2
3 namespace csharp6
4 {
5 internal class Program
6 {
7 private static void Main(string[] args)
8 {
9 Console.WriteLine("blackheart");
10 }
11 }
12 }

上面这段代码大家再熟悉不过了,使用静态类Console的静态方法WriteLine输出一行字符串。插播点关于CLR的相关知识,CLR在执行IL的期间时候是么有命名空间的概念的,它所知道的仅仅是成员的完全限定名(C#1 类型基础)。也就是在调用Console.WriteLine的时候,IL中使用的是完整的类型名称 System.Console.WriteLine 。打开ILDASM来看一看生成的IL代码,如下:

 1 .method private hidebysig static void  Main(string[] args) cil managed
2 {
3 .entrypoint
4 // Code size 13 (0xd)
5 .maxstack 8
6 IL_0000: nop
7 IL_0001: ldstr "blackheart"
8 IL_0006: call void [mscorlib]System.Console::WriteLine(string)
9 IL_000b: nop
10 IL_000c: ret
11 } // end of method Program::Main

那么,在我们需要调用Console的很多方法的时候,就需要去写很多遍的Console前缀,能否简化一下呢?

2. C#6 using static新语法

 1 using static System.Console;
2
3 namespace csharp6
4 {
5 internal class Program
6 {
7 private static void Main(string[] args)
8 {
9 WriteLine("blackheart");
10 }
11 }
12 }

重点部分在第一行 using static System.Console; ,我们使用“using static”引用了一个静态类型,System.Console,那么在当前这个全局作用域内,调用Console的任何静态成员,都可以省略掉Console.这个类型名前缀了。看起来是不是清爽多了!那么它的编译器做了什么奇妙的东西吗?我们用ILDASM看看IL,用IL来一探究竟:

 1 .method private hidebysig static void  Main(string[] args) cil managed
2 {
3 .entrypoint
4 // Code size 13 (0xd)
5 .maxstack 8
6 IL_0000: nop
7 IL_0001: ldstr "blackheart"
8 IL_0006: call void [mscorlib]System.Console::WriteLine(string)
9 IL_000b: nop
10 IL_000c: ret
11 } // end of method Program::Main

和老的语法编译的结果一模一样的,,,so,它的本质只是个语法糖而已

2.1 可以using static非静态类型吗?

答案是可以的,但是只能使用它的静态方法,至于原因,不用解释了吧。

 1 using static csharp6.MyClass;
2
3 namespace csharp6
4 {
5 public class MyClass
6 {
7 public void MyFunction(string value)
8 {
9 }
10
11 public static void MyStaticFunction(string value)
12 {
13 }
14 }
15
16 internal class Program
17 {
18 private static void Main(string[] args)
19 {
20 //不允许
21 MyFunction("blackheart");
22 //允许
23 MyStaticFunction("blackheart");
24 }
25 }
26 }

2.2 还有哪些类型可以使用using static?

除了class之外还支持structenum类型:

 1 using static csharp6.MyStruct;
2 using static System.ConsoleColor;
3
4 namespace csharp6
5 {
6 public struct MyStruct
7 {
8 public static void MyStructStaticFunction(string value)
9 {
10 }
11 }
12
13 internal class Program
14 {
15 private static void Main(string[] args)
16 {
17 //结构类型的静态函数
18 MyStructStaticFunction("blackheart");
19 //枚举ConsoleColor.Black
20 System.Console.ForegroundColor = Black;
21 }
22 }
23 }

2.3 using staitc成员签名与现有静态成员签名相同怎么处理?

现有静态成员优先级高,首选使用现有的静态成员。比如以下方法:

 1 using static System.Console;
2
3 namespace csharp6
4 {
5 internal class Program
6 {
7 private static void Main(string[] args)
8 {
9 //签名相同的非using static导入的方法优先级高
10 //所以会调用我们自己声明的WriteLine,输出“我的优先级比较高!”
11 WriteLine("blackheart");
12 }
13
14 //签名相同的WriteLine方法
15 private static void WriteLine(string value)
16 {
17 System.Console.WriteLine("我的优先级比较高!");
18 }
19 }
20 }

2.4 using static成员之间签名相同怎么处理?

先看下面这段代码:

 1 using static csharp6.MyClass;
2 using static System.Console;
3
4 namespace csharp6
5 {
6 public static class MyClass
7 {
8 public static void WriteLine(string value)
9 {
10 }
11 }
12
13 internal class Program
14 {
15 private static void Main(string[] args)
16 {
17 WriteLine("blackheart");
18 ReadKey();
19 }
20 }
21 }

我们using static了两个类型,这两个类型都有一个方法签名相同的WriteLine静态方法,编译器怎么处理呢?

编译器报错了,,,CS0121,告诉我们说在调用WriteLine的时候出现了歧义,它分不清楚我们要用哪个类型了。so,我们需要去掉一个using static或者使用老版本的写法

2.5 除了方法之外还能使用什么类型的成员?

静态属性,字段,事件等等,,,静态成员均可依靠using static 省略类型前缀。

 1 using static csharp6.MyClass;
2
3 namespace csharp6
4 {
5 class MyClass
6 {
7 public static void Method() { }
8 public static int Field;
9 public static int Property { get; set; }
10 public static event System.Action Event;
11 }
12 internal class Program
13 {
14 private static void Main(string[] args)
15 {
16 Method();//静态方法
17 var field = Field;//静态字段
18 var property = Property;//静态属性
19 Event += Program_Event;//静态事件
20
21 }
22
23 private static void Program_Event()
24 {
25 throw new System.NotImplementedException();
26 }
27 }
28 }

3. using static 扩展方法

既然using static可以应用在静态方法上,那么我们所熟知的在C#3中加入的扩展方法可以使用吗?答案是在特定的语法格式上可以扩展方法的第一个参数必须按照实例方法的调用方式书写才可以使用),笔者有点想不明白,扩展方法的实现是静态方法,只是第一个参数是一个特殊的this参数,为何直接用类型完全限定名可以用,而using static后缺不能使用呢?毕竟编译后都会翻译成完全限定名方式的调用。笔者实在想不明白。如下:

 1 using static System.Linq.Enumerable;
2
3 namespace csharp6
4 {
5 internal class Program
6 {
7 private static void Main()
8 {
9 //允许,本来就是非扩展方法。
10 var range = Range(5, 17);
11 //不允许,想不明白的地方
12 //var odd = Where(range, i => i % 2 == 1); // 不允许
13 //按原理来解释,上面的代码最终会翻译成这样,实在想不明白为何上面的方法不被允许
14 var odd = System.Linq.Enumerable.Where(range, i => i % 2 == 1);
15 //允许,这个和odd上面一个odd的编译效果是完全一样的
16 var odd2 = range.Where(i => i % 2 == 1);
17 }
18 }
19 }

4. 总结

本篇博文介绍了C#6的一个新语法特性,using static语法导入一个类型,然后就可以在其全局作用域范围内(当前文件内)使用它可以访问(遵循访问修饰符的限定)类型的静态成员了,需要注意的几点是:

  1. 导入的成员签名和现有的成员签名相同时,使用现有的成员。
  2. 导入的成员之间出现成员签名相同的情况,使用的时候会编译不通过,需要一处一个using static才可,或者改为正常的调用方式。
  3. class,struct,emun类型可以使用using static导人。
  4. 扩展方法也可以使用using static,但是需要按照实例方法的调用方式来使用。

最后,也是最要紧的是,using static仅仅是编译器的语法糖,帮助我们简化代码的,和之前的写法并无任何本质上的差异,编译后是无任何差别的。

5. 参考

C# 语言参考-using指令:Using Static Type

[C#6] 1-using static的更多相关文章

  1. static,你还敢用吗?(二)

    为了压系统,昨天小组在测试环境模拟了一大批订单数据.今天上午查看记录的账单计息日志,发现了一大堆的MySqlException MySql.Data.MySqlClient.MySqlExceptio ...

  2. const,static,extern 简介

    const,static,extern 简介 一.const与宏的区别: const简介:之前常用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽成宏,推荐我们使用const常量. 执行时刻:宏是预编 ...

  3. const extern static 终极指南

    const extern static 终极指南 不管是从事哪种语言的开发工作,const extern static 这三个关键字的用法和原理都是我们必须明白的.本文将对此做出非常详细的讲解. co ...

  4. PHP static静态属性和静态方法

    这里分析了php面向对象中static静态属性和静态方法的调用.关于它们的调用(能不能调用,怎么样调用),需要弄明白了他们在内存中存放位置,这样就非常容易理解了.静态属性.方法(包括静态与非静态)在内 ...

  5. static,你还敢用吗?

    我用火狐的HttpRequester测试开发组里一个同学发布的Web API接口,遇到了一个奇怪的问题. 我测试边界情况时,第一次调用响应的结果是正常的,但当再次及以后的请求时,却返回了异常“Syst ...

  6. Java关键字:static

    通常,当创建类时,就是在描述那个类的外观和行为.只有用new创建类的对象时,才分配数据存储空间,方法才能被调用.但往往我们会有下面两种需求: 1.我想要这样一个存储空间:不管创建多少对象,无论是不创建 ...

  7. Android 中关于static的使用问题

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/5251564.html 项目中,在不停地接收串口数据很长一段时间(几小时)后,会偶然性的报错.初步排除了oom ...

  8. iOS: 在UIViewController 中添加Static UITableView

    如果你直接在 UIViewController 中加入一个 UITableView 并将其 Content 属性设置为 Static Cells,此时 Xcode 会报错: Static table ...

  9. 浅谈Static关键字

    1.使用static关键字声明的属性为全局属性 未使用static关键字指定city之前,如果需要将Tom,Jack,Mary三人的城市均改成Beijing,需要再次声明三次对象的city为Beiji ...

  10. 今天思考一个问题,PHP const和static的区别

    static关键字在类中是,描述一个成员是静态的,static能够限制外部的访问,因为static后的成员是属于类的,是不属于任何对象实例,其他类是无法访问的,只对类的实例共享,能一定程序对该成员尽心 ...

随机推荐

  1. HTML5笔记:跨域通讯、多线程、本地存储和多图片上传技术

    最近做项目在前端我使用了很多新技术,这些技术有bootstrap.angularjs,不过最让我兴奋的还是使用了HTML5的技术,今天我想总结一些HTML5的技术,好记性不如烂笔头,写写文章可以很好的 ...

  2. MySql LIKE 查找带反斜线“\”的记录

    解决方法是在反斜线“\前加“\\\”三个反斜杠. SELECT * FROM 表名 AS a WHERE a.字段 \\\\qc0npwqe.3v4', '%') 原理: 写成三个'\'的原因是反斜线 ...

  3. 从java文件和CS文件里查询方法使用次数工具

    前几天,领导让我找一下老系统(Java)里getRemoteUser方法都哪个文件用了,package是什么,方法被调用了多少次,当时因为着急,所以,直接人工找的,但是以后要是再出现,人工找就太讨厌了 ...

  4. 完整记录一则Oracle 11.2.0.4单实例打PSU补丁的过程

    本文记录了打PSU的全过程,意在体会数据库打PSU补丁的整个过程. 1.OPatch替换为最新版本2.数据库软件应用19121551补丁程序3.数据库应用补丁4.验证PSU补丁是否应用成功 1.OPa ...

  5. RHEL 本地yum源配置

    1.创建挂载目录 # mkdir -p /media/cdrom   2.挂载对应系统版本的iso光盘镜像文件 # mount -o loop -t iso9660 /opt/rhel-server- ...

  6. Java对象序列化剖析

    对象序列化的目的 1)希望将Java对象持久化在文件中 2)将Java对象用于网络传输 实现方式 如果希望一个类的对象可以被序列化/反序列化,那该类必须实现java.io.Serializable接口 ...

  7. Unity3d连接SQL Server数据库出现SocketException: 使用了与请求的协议不兼容的地址错误

    这两天,同学问我Unity3d连接SQL Server的问题,当时我只是简单的说:“应该一样吧,就是那简单的几句啊”.之后他让我试了下,我才发现有问题了.故此写下一篇博客,要牢记这件事的教训,操作数据 ...

  8. Angular2 小贴士 Name

    Angular2 正式版已经发布了一个月了,我也是通过各种方式在进行验证是否可以满足我们的需求,今天我就发现了一个问题.现在我们来一起说明一下,这个可能不算是bug,而应该需要我们记住就可以了. 我们 ...

  9. 「译」JUnit 5 系列:扩展模型(Extension Model)

    原文地址:http://blog.codefx.org/design/architecture/junit-5-extension-model/ 原文日期:11, Apr, 2016 译文首发:Lin ...

  10. C#设计模式之简单工厂模式(Simple Factory)

    1. 概述 简单工厂模式就是将一个类的实例化交给一个静态工厂来执行. 2. 使用频率 中 3. 模式结构 3.1 机构图 3.2 模式中的角色 Product:抽象类,把具体产品类公共的代码进行抽象和 ...