关键字

  • 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#语言特性相关推荐

  1. 或许有一两点你不知的C语言特性

    关键字篇 volatile关键字 鲜为人知的关键字之一volatile,表示变量是'易变的',之所以会有这个关键字,主要是消除编译优化带来的一些问题,看下面的代码 1 int a = 8; 2 int ...

  2. 关于Python你不得不知道的Python语言特点

    首先什么是语言?什么是编程? 准确来说是:定义计算机程序的语言,用来向计算机发送指令 个人理解:   语言:是一种交流的工具或者方式.比如我们的汉语普通话.各地的方言.外语中的英语.俄语.日语等.我们 ...

  3. 从关键字~C语言 — 期末考,考研,面试中那些你不得不知道的C语言关键字细节

    目录 引言: 初步认识了C语言的结构之后 博主将带您进入关键字的世界了 1. 关于变量 1.1 什么是变量 1.2 变量的定义与声明 1.3 为什么要定义变量 1.4 变量定义的本质 2. 关键字 2 ...

  4. 10 个你可能还不知道的很酷JavaScript特性

    英文 | https://javascript.plainenglish.io/5-cool-javascript-features-you-might-not-know-about-yet-f2fc ...

  5. 你所不知道的js语言细节---1、函数的形参赋值

    函数形参赋值问题 ECMAscript中的所有函数都是按值传递的,也就是说,把函数外部的值复制给函数内部的参数.,就和把一个变量复制到另一个变量一样 基本类型 function addTime(num ...

  6. C语言你不得不知道的小知识

    C语言你不得不知道的小知识: 1: 常见的变量修饰关键字:static.const.extern.volatile.register static:(该变量保存在全局静态区)  a.修饰局部变量--& ...

  7. ES6 你可能不知道的事 – 基础篇

    ES6 你可能不知道的事 – 基础篇 转载 作者:淘宝前端团队(FED)- 化辰 链接:taobaofed.org/blog/2016/07/22/es6-basics/ 序 ES6,或许应该叫 ES ...

  8. 关于多线程编程您不知道的 5 件事 有关高性能线程处理的微妙之处

    虽然很少有 Java™ 开发人员能够忽视多线程编程和支持它的 Java 平台库,更少有人有时间深入研究线程.相反地,我们临时学习线程,在需要时向我们的工具箱添加新的技巧和技术.以这种方式构建和运行适当 ...

  9. 99.99%人都不知道的“##“里用法

    99.99%人都不知道的"##"里用法 转:原文链接<99.99%人都不知道的"##"里用法> 编者荐语: 来来来,学习一些C语言骚气的操作! 以下 ...

最新文章

  1. 怎么通过ip连接oracle,Oracle 无法通过IP连接问题
  2. canvas初体验之加载图片
  3. Focal Loss升级 E-Focal Loss让Focal Loss动态化,类别极端不平衡也得到提升
  4. 不区分大小写的内容比较
  5. Nodejs读写文件
  6. scala中使用Option、Some、None,避免使用null
  7. MAPLAP开发环境中release模式和debug模式烧写.hex文件的不同之处
  8. 路由器Lan、Wan短接问题
  9. [Flex] flex的安全沙箱,你保障了安全的同时也害苦了多少我这样的人那
  10. 路由器故障排除的思路与理论
  11. “做人难,人难做,难做人,做男人更难啊!
  12. Unicode字符串和非Unicode字符串
  13. windows10/win10开机自启动wifi热点
  14. 使用python制作字符视频(蔡徐坤唱跳rap字符视频)
  15. 4816 江哥的dp题b
  16. dataframe读取以文本形式储存的excel中的数字
  17. The Things Network LoRaWAN Stack V3 学习笔记 2.2 使用 CLI 进行 OAuth 登录
  18. Polhemus PATRIOT 电磁位置跟踪系统
  19. CPU后面的字母注解
  20. 接口测试平台代码实现54:首页重构-2

热门文章

  1. 使用log4Net 输出日志到mongodb
  2. 业务技术协同线上化的研发管理实战
  3. 【转载】【面试题】你是一个测试工程师,如何保证软件质量?
  4. Centos实现svn本地认证apache认证
  5. poj 1986 Distance Queries
  6. 话里话外:装备制造业企业迫切需要实现信息化综合集成
  7. 话里话外:企业内控的灵魂——企业文化
  8. 三星笔记本进入BIOS后找不到U盘启动项/快速启动键F12没有反应
  9. mysql数值类型总结及常用函数
  10. JavaScript中数组slice和splice的对比小结