你可能不知道的C#语言特性
关键字
yield
通常用于迭代器中,向IEnumerable对象提供值或者结束迭代。
如:
yield return expression; yield break;
var
用于定义隐式类型的变量。
var i = 5; var s = "Hello";
注意隐式类型(Implicitly typed)并不是“动态类型“,由编译器在编译时候决定具体类型。
default除了在switch语句中提供默认的条件之外,还作为关键字用于泛型中。比如:
T temp = default(T);
由于事先不知道T类型是引用还是值类型,无法用于和null(只有引用类型可以)或者数字(值类型才能和其比较)进行比较。用default关键字,会确保如果是引用类型则返回null,如果是值类型则返回0。
关键字global::用于引用全局命名空间。
class TestClass : global::TestApp { }
用于多线程中表示这个字段可以由多个同时执行的线程修改。更多有关如何使用volatile多线程的例子,可以参考如何:创建和终止线程。
public volatile int i;
和
C#中可以用extern修饰符声明外部实现的方法。常用于Interop服务使用非托管代码与DllImport属性一起使用(同时要声明static),如:
[DllImport("avifil32.dll")] private static extern void AVIFileInit();
C#中可以同时引用两个类型名完全相同的程序集(常见同一控件的多个版本),这时候使用外部命令行指定别名引用,比如:
/r:GridV1=grid.dll /r:GridV2=grid20.dll
在程序中使用它们的时候,需要用关键extern来引用它们:
extern alias GridV1; extern alias GridV2;
GridV1和GridV2会被引用进和全局命名空间同级别的额外空间,使用GridV1::Grid或者GridV2::Grid可以得到不同版本的Grid类型。
语法
??操作符
null合并运算符,用于定义可以为null值的引用类型的默认值。如果左操作数不为null,则返回左操作数,反之返回右操作数。
int y = x ?? -1;
同时这里也是null运算符:
static int? GetNullableInt() { return null; } //... or int? x = null;
where T:new()
我们知道可以用where关键字来对泛型定义进行约束,比如:
public class MyClass<T, U> where T : class where U : struct {}同时我们可以对泛型定义中包含构造函数的约束,new()约束告诉编译器提供的任何类型的参数都含有一个无参数的(默认)构造方法。
public class MyGenericClass<T> where T : IComparable, new() { T item = new T(); }
语言特性
Nullable类型
当我们要描述一个值类型可以不存在的的时候,使用nullable类型取代值类型。
使用?修饰符来声明一个nullable类型,比如:
int? a = 1;
C#通过Nullable类和Nullable结构体来支持nullable类型,Nullable结构体含有两个有用属性HasValue和Value来判断和获取当前类型是否还有值。
Curry化
这个名词对.NET的朋友可能有点生疏,wikipedia给的翻译是“柯里化”- 个人不太喜欢这个名字,英文是currying。curry化是函数式编程的一种实现技术。大致过程,就是把本来接受多个参数的函数,变成只有第一个参数的函数,然后返回新函数接受余下的参数。有点拗口,而且对函数式编程或curry化介绍的中文资料也相对较少,我读过一篇对函数式编程和curry化解释的比较清楚的文章还有这篇英文的博客,推荐大家看看。
所有能实现闭包的语言都可以实现curry化。在C#2.0中可以通过匿名委托来实现,在3.0中curry化相对简单一些:
static class Program { static Func<TArg1, Func<TArg2, TResult>> Curry<TArg1, TArg2, TResult>(this Func<TArg1, TArg2, TResult> f) { return a1 => a2 => f(a1, a2); } static void Main() { Func<int, int, int> add = (x, y) => x + y; var curriedAdd = add.Curry(); Console.WriteLine(curriedAdd(13)(29)); } }
最后,如果大家对用C#实现函数式编程有兴趣,可以在MSDN Code中找到更多的代码实现。
匿名类型
匿名类型可用来将一组只读属性封装到单个对象中,而无需首先显式定义一个类型。类型名称由编译器生成,并且不能在源代码级使用,类型也由编译器推断决定。常和LINQ查询表达式的select子句结合使用,初始化其他类型的属性组成的对象。
var productQuery = from prod in products select new { prod.Color, prod.Price }; foreach (var v in productQuery) { Console.WriteLine("Color={0}, Price={1}", v.Color, v.Price); }
扩展方法
C#3.0中可以对CLR扩充类型,比如,你可能需要得到一句英文字符串中有多少个单词,以往可以写一个处理string的方法,现在你可以直接为string类型添加一个计算单词数量的方法:
namespace ExtensionMethods { public static class MyExtensions { public static int WordCount(this String str) { return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length; } } }通过this我们把这个WordCount方法扩充到了CLR内置类型,你可以直接像用普通方法一样使用它:
using ExtensionMethods; //... string s = "Hello Extension Methods"; int i = s.WordCount();
更多介绍可以参考MSDN或者ScottGu的博客。
方法和属性
List.ForEach()
Array或List有个很实用的ForEach方法,可以直接传入一个方法对集合中元素操作。如:
List<String> names = new List<String>(); names.Add("Bruce"); names.Add("Alfred"); names.ForEach(Print); names.ForEach(delegate(String name) { Console.WriteLine(name); }); private static void Print(string s) { Console.WriteLine(s); }
GetValueOrDefault
对于nullable类型的对象,除了Value和HasValue两个常用属性外,还可以使用GetValueOrDefault方法来获得当前值或者默认值:
float? mySingle = 12.34f; float? yourSingle = -1.0f; yourSingle = mySingle.GetValueOrDefault(-222.22f); // yourSingle=12.34 mySingle = null; yourSingle = mySingle.GetValueOrDefault(); // yourSingle=0
技巧
使用大写字母比较字符串
摘自CLR via C#:
当比较字符串时候,推荐使用ToUpperInvariant 转换成大写而不是ToLowerInvariant 成小写。因为微软在比较大写字符串的时候对代码做了优化。
你可能不知道的C#语言特性相关推荐
- 或许有一两点你不知的C语言特性
关键字篇 volatile关键字 鲜为人知的关键字之一volatile,表示变量是'易变的',之所以会有这个关键字,主要是消除编译优化带来的一些问题,看下面的代码 1 int a = 8; 2 int ...
- 关于Python你不得不知道的Python语言特点
首先什么是语言?什么是编程? 准确来说是:定义计算机程序的语言,用来向计算机发送指令 个人理解: 语言:是一种交流的工具或者方式.比如我们的汉语普通话.各地的方言.外语中的英语.俄语.日语等.我们 ...
- 从关键字~C语言 — 期末考,考研,面试中那些你不得不知道的C语言关键字细节
目录 引言: 初步认识了C语言的结构之后 博主将带您进入关键字的世界了 1. 关于变量 1.1 什么是变量 1.2 变量的定义与声明 1.3 为什么要定义变量 1.4 变量定义的本质 2. 关键字 2 ...
- 10 个你可能还不知道的很酷JavaScript特性
英文 | https://javascript.plainenglish.io/5-cool-javascript-features-you-might-not-know-about-yet-f2fc ...
- 你所不知道的js语言细节---1、函数的形参赋值
函数形参赋值问题 ECMAscript中的所有函数都是按值传递的,也就是说,把函数外部的值复制给函数内部的参数.,就和把一个变量复制到另一个变量一样 基本类型 function addTime(num ...
- C语言你不得不知道的小知识
C语言你不得不知道的小知识: 1: 常见的变量修饰关键字:static.const.extern.volatile.register static:(该变量保存在全局静态区) a.修饰局部变量--& ...
- ES6 你可能不知道的事 – 基础篇
ES6 你可能不知道的事 – 基础篇 转载 作者:淘宝前端团队(FED)- 化辰 链接:taobaofed.org/blog/2016/07/22/es6-basics/ 序 ES6,或许应该叫 ES ...
- 关于多线程编程您不知道的 5 件事 有关高性能线程处理的微妙之处
虽然很少有 Java™ 开发人员能够忽视多线程编程和支持它的 Java 平台库,更少有人有时间深入研究线程.相反地,我们临时学习线程,在需要时向我们的工具箱添加新的技巧和技术.以这种方式构建和运行适当 ...
- 99.99%人都不知道的“##“里用法
99.99%人都不知道的"##"里用法 转:原文链接<99.99%人都不知道的"##"里用法> 编者荐语: 来来来,学习一些C语言骚气的操作! 以下 ...
最新文章
- 怎么通过ip连接oracle,Oracle 无法通过IP连接问题
- canvas初体验之加载图片
- Focal Loss升级 E-Focal Loss让Focal Loss动态化,类别极端不平衡也得到提升
- 不区分大小写的内容比较
- Nodejs读写文件
- scala中使用Option、Some、None,避免使用null
- MAPLAP开发环境中release模式和debug模式烧写.hex文件的不同之处
- 路由器Lan、Wan短接问题
- [Flex] flex的安全沙箱,你保障了安全的同时也害苦了多少我这样的人那
- 路由器故障排除的思路与理论
- “做人难,人难做,难做人,做男人更难啊!
- Unicode字符串和非Unicode字符串
- windows10/win10开机自启动wifi热点
- 使用python制作字符视频(蔡徐坤唱跳rap字符视频)
- 4816 江哥的dp题b
- dataframe读取以文本形式储存的excel中的数字
- The Things Network LoRaWAN Stack V3 学习笔记 2.2 使用 CLI 进行 OAuth 登录
- Polhemus PATRIOT 电磁位置跟踪系统
- CPU后面的字母注解
- 接口测试平台代码实现54:首页重构-2