唉!!,es6正看着呢;去海外组了。。。。要补c#知识了
.NET程序:
使用.NET兼容语言(如c#)编写程序 -> 把代码编译为CIL,存储在程序集中(即VS干的事)
-> 执行时,先使用JIT编译器将代码编译为本机代码 -> 在托管的CLR环境下运行本机代码。
基本类型
变量类型:
字节数增多:sbyte(1) short(2) int(4) long(8)
不同的是:其它类型的unsigned
前面加u
就好,唯独byte
是0到255
转义字符(\”表示”)和字面量(100L 100F)都和c++差不多
多了个新功能
|
|
差点忘了说,c#中变量类型其实全是System的类,也就意味着基本变量类型本身就有很多成员函数可以使用
typeof和GetType
c++的是typeid,记得mfc好像有个,忘了。
都返回System.Type
类型,一个是类函数一个是语言函数(参数是类名)。
switch语句
switch
语句有点不同,多了个goto case <com>:
,用来实现在这个case语句中跳转到其它case语句中
强制转换
用法基本同;c#多了层保险,可以用checked((type))
出现的崩溃来保证,高字节向低字节转换;也可以默认设置强制转换加check;在书67页。
枚举
用法和c++基本同;多了个指定类型,enum Type : long
,这样指定枚举变量的类型。
数组
|
|
数组的遍历可以用for
也可以用foreach(string f in fN)
;只是foreach
里的f是只读属性,不能写。
- 多元数组
|
|
- 锯齿数组
这个更该是数组中的数组,一个行不一定固定个数
|
|
元组
数组是合并相同类型,元祖就是合并不同类型
暂时我认为这个东西没啥用,不如用结构体。看以后吧!
匿名类型
var
会自动转换到相应的类型,当然也可以访问相应的成员函数。
nameof
把变量名变成字符形式
as和is
is会做俩次检查,as会做一次检查,as效率会高点
as类似于强制转换,转换失败便返回null
as只能用于引用类型和装箱转换,所以值类型还是得用is。除此外as还有隐式转换(见类的隐式显示)
函数
参数调用顺序是从左向右
函数定义
类中函数默认是private类型的,如果访问要public
函数可以重载,但是out
和ref
不能相同
lambda
|
|
函数参数
- 支持默认参数,同时不会在意默认参数位置(即不像c++那样默认参数必须放后面)
- 支持无序传入,
SName(kk:1, hh:2)
这种形式传入是支持的,但是如果这样写就必须把所有参数写完。
c#的委托和事件
|
|
delegate 至少0个参数,至多32个参数,可以无返回值,也可以指定返回值类型
泛型Action至少0个参数,至多16个参数,无返回值
泛型Func至少0个参数,至多16个参数,根据返回值泛型返回。必须有返回值,不可void(它最后一个参数才表示返回)
泛型Predicate有且只有一个参数,返回值固定为bool
后面的泛型较delegate的好处是,不用先声明再使用;可以直接使用。
它们都可以当参数传值。
|
|
##关于委托我想放个链接:http://www.cnblogs.com/r01cn/archive/2012/11/30/2795977.html
里面有多播/过滤/GetInvocationList(多播只能保证执行分别,而返回值是最后一个,而出现的)##
匿名
除了lamda外,还可以这样用匿名
事件
事件的实现严格需要代理的配合;关键字event
|
|
Action和Func
Action
本身就是代理只不过是返回void的代理;Action
Func
是有返回没参数的委托
其它
格式化输出
带运算;
Console.WriteLine($"{SName(1, 2)}")
;会运算了SName函数再输出;注意的是它和参数传入形式不能共存。参数传入;
Console.WriteLine("{0}a{1}", 10.02, 121);
这里0
表示后面第一个参数,随着参数增加,可以依次递增。
还有,它会完整输出参数的形式。不用担心是string、int、float,它全按参数形式输出。格式符;
只记录几个简单的:
D 十进制、N数字格式、X十六进制、P百分数格式;Console.WriteLine(String.Format("{0:N1}", 10))
这里{0:N1}表示第一个参数,按数字格式输出,小数点后留一位。
格式符后面的数字可增加,表示小数点后面的位数。但是格式符前面不能加数字,实在加要用占位符。占位符
1234string.Format("{0:0000.00}", 12394.039) 结果为:12394.04string.Format("{0:0000.00}", 194.039) 结果为:0194.04string.Format("{0:###.##}", 12394.039) 结果为:12394.04string.Format("{0:####.#}", 194.039) 结果为:194
零占位符:
如果格式化的值在格式字符串中出现“0”的位置有一个数字,则此数字被复制到结果字符串中。小数点前最左边的“0”的位置和小数点后最右边的“0”的位置确定总在结果字符串中出现的数字范围。
“00”说明符使得值被舍入到小数点前最近的数字,其中零位总被舍去。
数字占位符:
如果格式化的值在格式字符串中出现“#”的位置有一个数字,则此数字被复制到结果字符串中。否则,结果字符串中的此位置不存储任何值。
请注意,如果“0”不是有效数字,此说明符永不显示“0”字符,即使“0”是字符串中唯一的数字。如果“0”是所显示的数字中的有效数字,则显示“0”字符。
“##”格式字符串使得值被舍入到小数点前最近的数字,其中零总被舍去。
但是占位符又不简单的是这些:("{0:123##2.00}", 11)
输出:123112.00 ("{0:123##20.00}", 11)
输出:123121.00
看来实际用还得再测试下。
调试
调试信息的输出,这个调试信息是输出一行,比c++方便多了。Debug.WriteLine()
只能在debug模式下Trace.WriteLine()
任何模式下Debug.Assert()
Trace.Assert()
也支持try catch finally
finally必执行。
XML文档
这个我觉得很有必要。c++一般都是doxygen语法来,c#却这么高级直接官方支持(官方的snippets简直丧心病狂,太好用了)。
另外官方建议用Sandcastle
来生成相关阅读文档。
值列举常用的,详细:http://www.cnblogs.com/mq0036/p/3544264.html
summary:永远描述类型
remarks:添加有关类型的信息,补充summary
param:参数描述
returns:返回值描述
value: 属性说明(官方示例是set、get的那些属性)
example:示例代码部分
c:文本标记为代码
code:多行指示为代码
exception:异常说明
see:seealso:用<see cref="member"/>
预编译
|
类
this和base
类的定义
|
|
属性
大量例子对属性的使用都是这样的,感觉这个属性有点多余。
属性支持访问控制:get
和set
支持使用:public、private、protected来控制访问。
属性支持重写:abstract
、virtual
、override
这些可以联合使用
自动属性public double Height { get; set; }
构造函数和析构
基本和c++相同,允许重载、访问控制。
不同:
- 执行顺序(MyDericed继承基类);MyDericed myO = new MyDericed();1、执行System.Object.Object()构造函数;2、执行MyBaseClass.MyBaseClass构造函数;3、执行MyDericed构造函数
- 委托不同;12345public class MyD: MyBass{public MyD() : this(5, 6){}//委托给自身的另一个构造函数public MyD(int i, int j) : base(i) {}//调用基类构造函数}
对象初始化器
HeClass hh = new HeClass(2) { _me = 3 };
HeClass有个成员_me;
这个功能简直装逼用,没啥实用。效率和调用构造函数一样;
而且成员还必须是public,不然没法访问。。。。
##然后就是静态构造函数##
编写静态构造函数的一个原因是,类有一些静态字段或属性,需要在第一次使用类之前,从外部源中初始化这些静态字段和属性
由于并不确定它执行的时间,所以注意下此函数中对静态变量的赋值。
静态类
给类加个static只是告诉编译器,这个类的所有成员必须是static
类型的,不然就报错
类和结构体区别
c#中类和结构体有个大大的区别, 类是引用类型,结构体是值类型。
也就是说:
直接的=
操作对类来说是引用赋值(是浅拷贝过程)
直接的=
操作对结构体来说是复制信息(是深拷贝)
|
|
嵌套类
被嵌套在里面的类可以访问外部类的private成员,这和c++不同
对于嵌套类则不能把类型定义为protectcd、private和protected internal,
因为这些修饰符对于包含在名称空间中的类型没有意义。因此这些修饰符只能应用于成员。
但是,如果是嵌套类的话,这些修饰符就有了些意义。
其它定义字段
|
|
c#的extern导入的是外部程序集,经常和DllImport联合使用。
继承使用
c#的virtual、override、更是不同
partial部分关键字的使用
partial关键字允许把类、结构或接口放在多个文件中,编译再变成一个类。
包括继承对象也会整合在一起(但是访问权限关键字不能整合)
浅拷贝和深拷贝
浅拷贝由默认隐式转换和MemberwiseClone来完成不用说。
来看深拷贝代码:
重载符函数
|
|
如上操作符函数有这些要求:
必须是public
必须是static
返回值必须是原型
一元运算符:+、-、!、~、++、–、true、false
二元:+、-、*、/、%、&、|、^、<<、>>
比较:==、!=、<、>、<=、>=
隐式转换和显式转换
对于引用类型来说,如下代码有误:
继承
函数隐藏
c#会像c++那样出现函数隐藏,但是它面对函数隐藏的时候会报警告的,如果要消除警告:
Object类
所有类都派生于System.Object
,即使定义时没指定基类也会默认继承。
abstract和sealed
abstract
对类;修饰并不能阻止其函数的定义,也无法使函数默认变成可重写类型(函数依旧需要自己声明重写类型);
它对类来说就只能是个说明是接口类的作用,实际作用并没有。abstract
对函数;此函数为虚函数,默认重写类型sealed
对类;这样表示此类不能被继承sealed
对函数;只能对可重写类型的函数才能使用(virtual abstract),表示此函数子类不能重写,常和override
联合使用
拆箱和装箱
首先这俩个操作是隐式的
所有值类型均隐式派生自System.ValueType:
结构体、数值、整形、字符(char)、浮点、bool、枚举、派生于System.Nullable
如int i = new int()
等价于int i = 0
所有引用类型均隐式派生自System.object(包括它本身):
数组:(派生于System.Array)数组的元素,不管是引用类型还是值类型,都存储在托管堆上;
类:class(派生于System.Object);
接口:interface(接口不是一个“东西”,所以不存在派生于何处的问题。);
委托:delegate(派生于System.Delegate);
object:(System.Object的别名);
字符串:string(System.String的别名)。
今天测试了下,发现string却可以像值类型那样运作,搜索了下:
string最为显著的一个特点就是它具有恒定不变性:我们一旦创建了一个string,在managed heap 上为他分配了一块连续的内存空间,我们将不能以任何方式对这个string进行修改使之变长、变短、改变格式。
所有对这个string进行各项操作(比如调用ToUpper获得大写格式的string)而返回的string,实际上另一个重新创建的string,其本身并不会产生任何变化。
每次改变值时都会建立一个新的string对象,变量会指向这个新的对象,而原来的还是指向原来的对象,所以不会改变。这也是string效率低下的原因。
|
|