1、类型推导

var age = ;
Console.WriteLine(age.GetType().ToString());

var 关键字还可以配合生成匿名类型,如:

var log = new {Userid = "", OpeType = , Time = };

如果有可以将对象转成JSON的方法,就可以非常方便的生成各种动态JSON数据了。

2、公共基类

公共基类 object 是 System.Object 的假名,所有类都继承自 System.Object 类,比如所有对象都可以重写 ToString() 方法。

3、在字符串前面加上 @ 符号,表示非转义字符串。

如 string filepath = @"C:\Windows\test.cs";

4、switch语句支持将字符串作为测试变量

5、枚举

枚举的强大之处是它们在后台会实例化为派生于基类System.Enum的结构,从而可以调用方法执行一些任务。

 using System;

 namespace Learn
{
public enum TimeOfDay
{
Morning = ,
Afternoon = ,
Evening = ,
} class MainClass
{
public static void Main (string[] args)
{
var name = @"\tLuna";
Console.WriteLine ("name: " + name + "\ttype: " + name.GetType ().ToString ()); var log = new {Userid = "", OpeType = , Time = };
Console.WriteLine (log.GetType ().ToString ()); var platform = "iOS";
switch (platform) {
case "ios":
Console.WriteLine ("iOS");
break;
case "android":
Console.WriteLine ("Android");
break;
default:
Console.WriteLine ("other");
break;
} TimeOfDay time = TimeOfDay.Afternoon;
//note: `time` 输出的是枚举名,而不是枚举值
Console.WriteLine (time);
Console.WriteLine (time.ToString ()); //同 `time`
//枚举项可以看成 INT 的装箱类型,所以使用强转拆箱操作即可获取枚举值
Console.WriteLine ((int)time);
//通过给定字符串获取枚举对象
var t = "1morning";
try {
TimeOfDay time2 = (TimeOfDay)Enum.Parse (typeof(TimeOfDay), t, true);
Console.WriteLine (time2);
} catch (Exception e) {
Console.WriteLine (e.ToString ());
}
} //override
public override string ToString ()
{
return string.Format ("[MainClass]");
}
}
}

6、编译

使用 /target 选项(简写成 /t)来指定要创建的文件类型,如

/t:exe    控制台应用程序(默认)
/t:library  带有清单的类库
/t:module  没有清单的组件
/t:winexe  Windows应用程序(没有控制台窗口)

还有 /out 选项用于指定输出文件名

/reference  选项(简写成 /r)指定链接库

7、预处理器

#define 和 #undef  定义某个变量/取消定义某个变量

#if、#elif、#else 和 #endif  常常和 #define/#undef 指令配合使用,如果某个变量被定义,则执行某逻辑,最常用于跨平台代码、debug/release代码区分。

#warning 和 #error 指令用于让编译器产生警告和错误,常配合上面的指令使用,用于判定是否错误设定了 #define 指令。

#pragma 忽略或还原某类编译警告,比如使用了第三方库报了警告,又不方便去修改它,作为强迫症患者可能就需要使用这个指令了。

 using System;
namespace Learn
{
class MainClass
{
public static void Main (string[] args)
{
//C#的预定义功能,只支持`是否存在`的定义,而不支持`值判断`的定义
//比如 UNITY 默认根据当前平台,定义了相应的宏
string platform = "";
#if UNITY_EDITOR_WIN
platform = "UNITY_EDITOR_WIN";
#elif UNITY_EDITOR_OSX
platform = "UNITY_EDITOR_OSX";
#elif UNITY_IOS
platform = "UNITY_IOS";
#elif UNITY_ANDROID
platform = "UNITY_ANDROID";
#else
#error "platform is undef!"
#endif
Console.WriteLine (platform);
}
}
}

8、参数类型

默认引用类型都是通过引用传递,值类型都是通过值传递。如果希望将值类型通过引用传递,可以使用 ref 参数。不同于 C/C++,C#中的 ref 参数必须在使用前赋值,所以也就不方便像C/C++那样通过引用类型参数作为输出参数了,C#中的输出参数使用 out 参数,out 参数也是引用传递,机制跟 ref 参数相同,只是在使用前不需要初始化。

将引用参数和输出参数按功能性用不同的关键字分离开来,我觉得还是不错的。

注意,C# 调用有 ref 参数或 out参数的函数时,要显式代入 ref 关键字和 out 关键字。

调用函数时,默认按参数顺序依次代入参数,但也可以根据参数名显式代入参数,如此则不需要按顺序代入。

可选参数必须放在参数列表的最后,而且必须有默认值。

public void Calc(ref int num,out bool b) {
num *= ;
b = true;
} public static void Main (string[] args)
{
int num = ;
bool b;
var obj = new MainClass ();
obj.Calc (ref num,out b);
Console.WriteLine ("num: " + num + "\tb: " + b);
}

9、字段与属性

字段一般为小写(很多人习惯为字段添加下划线前缀)且为私有,而属性则是用来访问/修改字段的访问器,可以为访问器设置不同的访问修饰符,来控制访问权限。

可以书写自动实现的属性,这样就不需要声明字段,编译器会自动创建它。如 public int Age {get; set;}

readonly字段 和 const字段:

readonly 比 const 要灵活得多,const 用于修饰成员字段时,需要显示声明为 static ,且在声明时必须指定初始值。而 readonly 字段可以作为普通成员字段(意即每一个实例都可以有一个不同的常量),也可以作为static成员字段,它可以在构造函数里进行赋值,而不能在其它地方赋值。

 using System;
namespace Learn
{
class User
{
private int _Gold;
public int Gold
{
get
{
return this._Gold;
}
set
{
if (value < )
{
this._Gold = ;
}
}
}
} class MainClass
{
public static void Main (string[] args)
{
User user = new User ();
user.Gold = ;
user.Gold -= ;
Console.WriteLine (user.Gold); //print `0`
}
}
}

10、struct

C#也同样支持 struct,与 class 不同的是, C# 的 struct 是值类型,不支持继承,而且其默认构造函数不允许替换(即不允许重写无参构造函数),不能在类中直接初始化成员(默认都初始化成初值,如数值全部初始化为0),必须先为struct成员赋值后才可使用,分配于栈中。

所以如果是 User user; 这样的代码,如果User 是一个 class,将会编译出错(未初始化的引用),而如果是 struct,则不会,因为栈中变量的声明实际上就已经在栈中分配空间了。

因为结构是分配于栈中,所以生成和删除的速度都很快,但又因为结构是值类型,所以作为参数传递效率又很低,所以何时使用结构要根据实际情况而定。

struct 派生自 System.ValueType,而 System.ValueType 又派生自 System.Object.

11、强引用和弱引用

一般声明一个对象等操作,都是强引用,这样垃圾回收器就不会回归该资源,但有时由于对象特别大,并不希望总是占用资源,可以使用弱引用,弱引用使用 WeakReference 类创建,因为弱引用对象随时会被回收,所以在使用之前,必须先确定该对象仍然存在,如:

WeakReference userRef = new WeakReference(new User());
GC.Collect();  //手动调用垃圾回收,但不保证立即回收弱指针
if(userRef.IsAlive)
{
  User user = userRef.Target as User;
}

12、部分类

C#允许将一个类的实现拆分多个文件中,其好处是一方面可以将一个庞大的类按功能拆分,另一方面,对于扩展一个类功能也非常方便(尤其是对于扩展第三方库的类)。

13、扩展方法

扩展方法是静态方法,尤其对于不能修改源代码的第三方库,可以通过此方式来扩展功能。在一个静态类中,用一个静态方法来实现扩展方法,扩展方法的第一个参数是要扩展的类型,且需要使用 this 关键字修饰,扩展方法内部可以访问所扩展类型的所有公有方法和属性。在调用扩展方法时,跟调用普通的成员方法一样,都是使用实例去调用,如:

public static class MoneyExtension
{
  public static void AddToAmount(this Money money, int add)
  {
    money.Amount += add;
  }
}

14、继承

  C#不允许多重实现继承(C++支持多重实现继承,有其优点,但缺点也是显而易见的,非常难以理解和调试),但支持多重接口继承。

  虚方法和虚属性,只有声明为 virtual 的方法和属性,才可以在派生类中重写,重写时需要使用 override 关键字显式声明(C++没有override,所以当误写了方法签名时,编译器是不会报错,它会以为你只是声明了一个新的方法,而C#则无此问题),如果派生类中实现了一个和基类完全相同签名的方法(没有使用 virtual 和 override),则会隐藏基类的方法,在C#中隐藏一个基类的方法,需要使用 new 关键字显式标明,否则编译器会给出警告。(一切都是为了更明确,减少风险)

  抽象类和抽象函数使用 abstract 关键字修饰,抽象类不能被实例化,抽象函数不能被直接实现,只能在派生类中重写(抽象类其实也是 virtual 的)。

  密封类和密封方法,为了防止类被继承或方法被重写,可以使用 sealed 关键字修饰。密封类一般用于商业原因中,不希望第三方扩展自己的功能而使用。string 类就是一个密封类,了解即可。

  在调用派生类构造函数时,总是先根据继承树检查基类,先调用基类的构造函数,所以继承树中的构造函数调用,是从System.Object类开始依次调用的。派生类构造函数默认需要调用基类的默认构造函数,如果基类没有默认构造函数(设置为private或重载了构造函数),则会编译错误,需要显式的调用基类其它构造函数。(我需要写写demo测试一下)

  接口可以继承接口。

15、泛型

  泛型的默认值不能使用 null,因为泛型类型也可以实例化成值类型,而 null 只能表示引用类型。为了解决这个问题需要引入 default 关键字。

 public T Pop()
{
T item = default(T);
if (list.Count > ) {
item = list.First.Value;
list.RemoveFirst ();
}
return item;
}

  如果泛型类需要调用泛型类型中的方法,就必须添加约束,比如要求 T 必须满足什么接口等,泛型约束有6种:

 where T : struct    //值类型
where T : class //引用类型
where T : Interface //实现某个接口
where T : BaseClass //继承某个基类
where T : new() //必须有一个默认构造函数
where T : T2 //T 派生自泛型类型T2,也称为裸类型约束

  泛型类也是一个类,可以实现一个接口或继承另一个类,比如常见的实现 IEnumerable<T> 接口

  泛型类也可以声明静态成员,泛型类的静态成员只能在类的一个实例中共享,如:

public class Test<T>
{
public static int x;
} class MainClass
{
public static void Main (string[] args)
{
Test<int>.x;
Test<string>.x;
}
}

  协变和抗变,貌似在unity中是有问题的。还有泛型结构: Nullable<T> ,暂且略过。

C#的更多相关文章

  1. 【小程序分享篇 二 】web在线踢人小程序,维持用户只能在一个台电脑持登录状态

    最近离职了, 突然记起来还一个小功能没做, 想想也挺简单,留下代码和思路给同事做个参考. 换工作心里挺忐忑, 对未来也充满了憧憬与担忧.(虽然已是老人, 换了N次工作了,但每次心里都和忐忑). 写写代 ...

  2. 前端开发中SEO的十二条总结

    一. 合理使用title, description, keywords二. 合理使用h1 - h6, h1标签的权重很高, 注意使用频率三. 列表代码使用ul, 重要文字使用strong标签四. 图片 ...

  3. 【疯狂造轮子-iOS】JSON转Model系列之二

    [疯狂造轮子-iOS]JSON转Model系列之二 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇<[疯狂造轮子-iOS]JSON转Model系列之一> ...

  4. 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新

    上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...

  5. 谈谈一些有趣的CSS题目(十二)-- 你该知道的字体 font-family

    开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...

  6. MIP改造常见问题二十问

    在MIP推出后,我们收到了很多站长的疑问和顾虑.我们将所有疑问和顾虑归纳为以下二十个问题,希望对大家理解 MIP 有帮助. 1.MIP 化后对其他搜索引擎抓取收录以及 SEO 的影响如何? 答:在原页 ...

  7. 如何一步一步用DDD设计一个电商网站(二)—— 项目架构

    阅读目录 前言 六边形架构 终于开始建项目了 DDD中的3个臭皮匠 CQRS(Command Query Responsibility Segregation) 结语 一.前言 上一篇我们讲了DDD的 ...

  8. ASP.NET Core 之 Identity 入门(二)

    前言 在 上篇文章 中讲了关于 Identity 需要了解的单词以及相对应的几个知识点,并且知道了Identity处在整个登入流程中的位置,本篇主要是在 .NET 整个认证系统中比较重要的一个环节,就 ...

  9. MVVM模式和在WPF中的实现(二)数据绑定

    MVVM模式解析和在WPF中的实现(二) 数据绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...

  10. Key/Value之王Memcached初探:二、Memcached在.Net中的基本操作

    一.Memcached ClientLib For .Net 首先,不得不说,许多语言都实现了连接Memcached的客户端,其中以Perl.PHP为主. 仅仅memcached网站上列出的语言就有: ...

随机推荐

  1. Mysql常用函数,难点,注意

    一.数学函数 ABS(x)   返回x的绝对值 BIN(x)   返回x的二进制(OCT返回八进制,HEX返回十六进制) CEILING(x)   返回大于x的最小整数值 EXP(x)   返回值e( ...

  2. .net framework体系结构

    CIL(common intermediate language):公共中间语言..net框架下各种种类.版本的编程语言在经过编译后生成的中间语言(后缀为.il),与平台无关.与语言无关,只要机器上运 ...

  3. 烂泥:学习centos之快速搭建LNMP环境

    本文由秀依林枫提供友情赞助,首发于烂泥行天下 以前在centos下安装软件都是喜欢源码安装,不过昨天因为一个事情需要一个centos 下的LNMP环境.反倒不会搞了,今天特意记录下,以备后续使用. 一 ...

  4. 【FLUENT案例】03:冲蚀

    1 引子2 问题描述3 模型准备4网格5模型设置6 材料设置7 设定注入器8 修改材料9 Cell zone Conditions设置10 边界条件设置10.1 inlet入口设置10.2 出口设置1 ...

  5. Maven build lifecycle

    Clean Lifecycle 运行mvn clean执行clean生命周期,包含三个生命周期阶段: pre-clean clean post-clean clean:clean会删除一次构建后的输出 ...

  6. kettle中全局变量的设置

    设置全局变量. 找到.properties文件: 在文件中设置值: 在kettle中新建一个job(不用做任何设置): 转换中获取便元的设置: 重启kettle的执行结果:

  7. 如何将网页的title前面的图标替换成自己的图标

    首先要准备自己的图标,图标必须是.ico格式的图片,网上有很多在线工具可以将自己的图片转换成ico格式的图片,这里给大家介绍两个网站 在线ico转换工具:生成的图标是可以选尺寸的,原图片的大小不限制 ...

  8. c# MongoDB 经纬度应用示例

    class Program      {          static string mongodb = "mongodb://127.0.0.1:27017";        ...

  9. Weekly Traning Farm 16

    先安利一下这套比赛,大概是doreamon搞的,每周五晚上有一场,虽然没人做题目质量挺高的 http://codeforces.com/group/gRkn7bDfsN/contests(报名前要先报 ...

  10. go http.Get请求 http.Post请求 http.PostForm请求 Client 超时设置

    http中有Get/Post/PostForm方法 也可以通过http包中设置client 请求配置 ,然后通过client.Do方法实现请求 下demo中功能都实现,其中有详细说明: package ...