CLR VIA C# 学习笔记
第19章 可空类型
1)使用Nullable<T>可将int32的值类型设置为Null,CLR会在Null时默认赋值为0;
如:Nullable<T> x=null; //使用x. GetValueOrDefault()
2)也可使用?代替,如下:
Point? pt = null;//new Point();
int x1 = pt.GetValueOrDefault().X;
int y1 = pt.GetValueOrDefault().Y;
3)注意使用可空实例IL会生成大量代码
4) C#的空接合操作符
使用??操作符,假如左边的操作符不为空,则返回这个操作符的值,如果为空则使用右边的操作数的值,类型数据库中的isnull, 如:int x=b??123; //若b为空则x=123;
有人争辩说??不过是?:的语法糖,其实??能够很好的支持表达式
func<string> f=()=>somethod()??”mark”;
第12章
泛型为开发人员提供以下优势:
1) 源代码保护
2) 类型安全,试图使用不兼容的类型的一个对象会造成编译错误,或运行异常。
3) 更清晰的代码,减少代码中必须进行的转型次数
4) 更佳的性能,想要进行常规化的算法,必须定义操作object类型
12.1
1)要使用线程安全的泛型集合类,去system.collection.concurrent命名空间,建议开发人员使用泛型集合类,不鼓励使用费泛型集合. 泛型比非泛型更好的对象模型,虚方法明显减少,从而获得更好的性能,泛型集合类添加了新成员,为开发人员提供了新的功能。
12.3 泛型基本结构
泛型从CLR 2.0增加,为了加入泛型的支持,微软必须完成以下工作:
创建新的IL指令,使之能够识别类型实参
修改现有元数据表格式,以便表示具有泛型参数的名称和方法
修改JIT编译器
创建新的反射成员,使之能查询类型和成员。
修改调试以显示和操纵泛型、成员、局部变量
修改vs 的职能感应特性。
12.3.1 开发类型和封闭类型
具有泛型类型参数的类型称为开发类型,clr禁止构造开放类型的任何实例。
为所有类型实参传递的都是实际数据类型,则称为封闭类型.CLR允许构造封闭类型的实例。
Type t=typeof(Dictionary<,>); //Dictionary<,> 开放类型
t=typeof(Dictionary<Guid>) //Dicionary<Guid>是一个封闭类型
CLR会在类型对象内部分配类型的静态字段,每个封闭类型都有自己的静态字段,换言之,假如List<T>定义了任何静态字段,这些字段不会再一个List<datetime>和一个List<string>之间共享,每个粉笔类型对象都有它自己的静态字段。在泛型类型上课定义一个静态构造函数,目的是保证传递的类型实参满足特定的条件。如果希望一个泛型类型只处理枚举类型,就可以再静态构造函数进行定义判断,若类型T不是枚举,则报错。
12.3.2
例子: 1)List<Datetime> dt=new list<datetime>
一些开发人员可能首先定义下面这样的一个类:
internal sealed class DatetimeList:List<Datetime>{}
这样做表面,方便了,但是绝对不要单纯出于增强源代码的目的定义一个新类,这样会丧失类型同一性和相等性.若要这样做,可以再源码文件的顶部使用using指令
using DateTimeList = System.Collections.Generic.List<System.DateTime>;
12.3.4 代码爆炸
假如某个类型实参是值类型,CLR必须专门为哪个类型生成本地代码。这是因为值类型的大小不定。即使两个值类型具有相同的大小(比如int32和Uint32,两者都是32位),CLR仍然无法共享代码,因为可能要用不同的本地CPU指令来操作这些值。CLR会认为所有引用类型实参都是相同的,所以代码可共享。如list<stream>与list<string>,都会使用相同的代码。
12.3.3 建议尽量使用在FCL中预定义的泛型action,func委托
12.3.4 委托的协变与逆变
1)不变量:泛型类型参数不能更改。
2)协变量: 泛型类型参数可以从一个基类更改为该类的派生类.在c#中用in关键字标记逆变量形式的泛型类型参数,逆变量泛型类型参数只出现在输入位置。比方方法的参数。
3)逆变量:泛型类型参数可以从一个派生类更改为它的基类。C#中,用out关键字标记协变量想成的泛型类型参数。协变量泛型类型参数职能楚翔在输出位置,比如方法的返回类型。
注意:只有在编译器能够验证类之间存在一个引用转换的前提下,才能应用这些可变性。
12.9.1 主要约束
类型参数可以指定一个主要约束,不能指定一下特殊引用类型:object,array,delegate,multicastDelegate,valueType,enum,void.
public class primaryclass<T> where T:stream{}
有两个特殊的约束:CLASS 和struct.
12.9.2次要约束
一个类型参数可以指定零个或多个次要约束,次要约束代表的事一个借口类型。指定一个借口类型约束时,是向编译器承诺一个指定的类型实参是实现了接口的一个类型。
12.9.3 构造器约束
一个类型参数可以指定零个或者一个构造器约束。指定构造器约束相当于向编译器承诺:一个指定的类型实参是实现了公共无参数器的一个非抽象类型。
class constructorConstraint<T> where T:new()
14.字符串处理注意事项:
1)定义换行:string s=”HI\r\nthere”;一般不建议这样做,相反System.Environment类型定义了一个只读NewLine属性。建议做法:string s = "HI" + Environment.NewLine + "There";
2)若要运行时讲几个字符串连接在一起,请避免使用+操作符,因为它会在堆上穿件多个字符串对象,而堆是需要垃圾回收的,从而影响性能。想反,应尽量使用StringBuilder类型。
14.2.2
string 对象最重要的一个事实是:它是不可变的,也就是说,字符串一经创建不能更改,不能变长,变短,修改其中任何字符。使字符不可变,还意味着在操纵或访问一个字符串时不会发生线程同步问题。
13.2.3
判断字符串相等或对字符串进行排序时,强烈建议调用下列方法之一:
Equals,compare,startweith,endswith.
应该总是区分大小写的比较,原因是假如只是大小写不同的两个字符串被视为相等,那么每次对他们进行排序,他们都可能 按照不同排序排列,从而造成用户迷惑。
如果对大量不同字符串反复执行同一个比较,强烈建议使用System.stringComparer类。
避免使用compareOrdinal及==和!=操作符,之所以避免使用这些方法和操作符,是因为调用者不显式指出以什么方式执行字符串比较,而你无法从方法名看出默认的比较方法,默认情况下,Compareto会执行依赖于语言文化的比较。主要考虑到语言文化的不同。
10. 属性
10.1.1 自动实现属性AIP
如果声明一个属性而不提供get/set方法的实现,C#会自动为你声明一个私有字段。
使用AIP,意味着你已经创建了一个属性,访问该属性的任何代码实际都会调用GET,SET方法。如果以后决定自己实现get或set方法,而不是接受编译器的默认实现,访问属性的任何代码都不必重新编译。如果将name声明为字段,以后又想把它更改为属性,那么访问字段的所有代码都必须重新编译,以便访问属性的方法。
1) 字段声明语法可能包含初始化部分,所以要在一行代码声明并初始化字段。但是没有简单的语法初始化AIP。所以必须在每个构造器中显示初始化每个AIP。
2) 运行时序列化引擎将字段名持久存储到序列化的流中。在任何想要序列化或反序列化的类型中,都不要使用AIP功能。AIP的支持字段的名称是有编译器决定的,而且每次从新编译代码,都可能更改这个名称,任何类型只要含一个AIP,便没办法对该类型的实例进行反序列化了。
3) 进行调试时,不能再AIP的get,set方法添加断点,所以不好检测应用程序在什么时候获取或设置这个属性
AIP是作用于整个属性的,要么都用,要么都不用,不能显示实现一个访问器方法,让另一个自动实现。
10.1.2合理使用属性
1)属性看起来和字段相似,实际是方法。
2)属性可以是只读,只写,字段却可以总是只读只写。
3)属性方法可以抛出异常,字段不会。
4)属性不能作为out ,ref作为参数传递给方法,字段可以。
5)许多人使用属性的一个常见原因是执行线程同步,它可能早晨线程永远终止。因此如果需要线程同步,就不应使用属性,最好使用方法。如果此类可以被远程访问,那么调用属性方法会非常慢。因此在这种下,应该优先使用方法,在个人看来,从MashalByRefObject派生的类永远都不应该使用属性。
6)属性方法可能需要额外的内存,或者返回不正确的引用。
10.1.3 对象和集合初始化器
Employee e=new Employee(){name=”jack”,age=30};
10.1.4 匿名类型
1)var的使用,主要和dynamic的区别。
用var声明局部变量只是一种简化语法,它要求编译器根据一个表达式推断具体的数据类型。Var关键字职能用于声明方法内部的局部变量,而dynamic关键字可用于局部变量、字段和参数。
Var o1=new {name=”jack”,age=30};
Dynamic是运行时解析
//动态使用expandoObject的用法
dynamic e = new System.Dynamic.ExpandoObject();
e.x = "aa"; e.y = "bbb";
//e.z = "xxx";
return e.x.ToString() + e.y + e.z;
2)使用Tuple,支持7个参数的类型
//第一种语法
return new Tuple<int, int>(Math.Max(value1, value2), Math.Min(value1, value2));
//第二中语法
return Tuple.Create(Math.Max(value1, value2), Math.Min(value1, value2));
10.2 有参属性
c#语言把有参属性称为索引器
C#只允许在对象的实例上定义索引器,c#没有提供定义静态索引器属性的语法。
一个类型可定义多个索引器,只要索引器的参数集不同即可。
Class BitArray
{ public bool this[int 32 bitpos]
{}}
第9章 .参数
1)参数默认值的使用
2)out:如果方法的参数用Out来标记,表明不指望调用者在调用方法之前初始化好了对象。被调用的方法不能读取参数的值,而且在返回前必须向这个值写入。想法,如果方法的参数用ref来标记,调用者就必须在调用方法前初始化参数的值,被调用的方法可以读取值以及或者向值写入。
3)可变数量的参数 params关键字告诉编译器向参数应用一个system.paramArrayAttibute的一个实例。
4)dynamic类型,在通过 dynamic 类型实现的操作中,该类型的作用是绕过编译时类型检查, 改为在运行时解析这些操作。该类型简化了对 COM API(例如 Office Automation API)、动态 API(例如 IronPython 库)和 HTML 文档对象模型 (DOM) 的访问。在大多数情况下, dynamic 类型与 object 类型的行为是一样的。 但是,不会用编译器对包含 dynamic 类型表达式的操作进行解析或类型检查。 编译器将有关该操作信息打包在一起,并且该信息以后用于计算运行时操作。在此过程中,类型 dynamic 的变量会编译到类型 object 的变量中。 因此,类型 dynamic 只在编译时存在,在运行时则不存在。
CLR VIA C# 学习笔记的更多相关文章
- .NET编程和SQL Server ——Sql Server 与CLR集成 (学习笔记整理-1)
原文:.NET编程和SQL Server ——Sql Server 与CLR集成 (学习笔记整理-1) 一.SQL Server 为什么要与CLR集成 1. SQL Server 提供的存储过程.函数 ...
- CLR via C#学习笔记----知识总概括
第1章 CLR的执行模型 托管模块的各个组成部分:PE32或PE32+头,CLR头,元数据,IL(中间语言)代码. 高级语言通常只公开了CLR的所有功能的一个子集.然而,IL汇编语言允许开发人员访问C ...
- (CLR via C#学习笔记)异步操作 - 线程池
一 线程池基础 1.线程池维护了一个操作请求队列,将请求的操作追加到线程池队列中,线程池的代码从队列中提取操作项,派发给线程池中的线程; 2.CLR初始化时,线程池中是没有线程的,当有操作派发给线程池 ...
- (CLR via C#学习笔记)线程基础
一 使用线程的理由 1.可响应性(通常是对于客户端GUI应用程序);2.性能,多个CPU(或多核CPU)能并发执行多个线程,同时执行多个操作能提升性能. 二 线程开销 线程有空间(内存耗用)和时间(运 ...
- CLR via C#学习笔记---类型
类的内存分配:http://www.cnblogs.com/JimmyZhang/archive/2008/01/31/1059383.html 关键字: abstract (类)该类不能构建 ...
- (CLR via C#学习笔记)任务和并行操作
一 任务 可以调用ThreadPool的QueueUserWorkItem方法发起一次异步的计算限制操作.但这个技术有很多限制.最大的问题是没有内建的机制让你知道操作在什么时候完成和操作完成时的返回值 ...
- 公共语言运行库(CLR)开发系列课程(1):Pinvoke 简介 学习笔记
前言 让拖管代码对象和非托管对象协同工作的过程称为互用性(Interoperability),通常简称为 Interop. P/Invoke在托管代码与非托管代码交互式时产生一个事务(Transiti ...
- [C#] 类型学习笔记一:CLR中的类型,装箱和拆箱
在学习.NET的时候,因为一些疑问,让我打算把.NET的类型篇做一个总结.总结以三篇博文的形式呈现. 这篇博文,作为三篇博文的第一篇,主要探讨了.NET Framework中的基本类型,以及这些类型一 ...
- linq学习笔记
最近在学习linq的一些基础知识,看了c#高级编程及阅读了园子内部几篇优秀的博文,有所体会,感觉应该记录下来,作为以后复习使用.都是一些最基础的知识,大致分为三个部分:linq预备知识:linq查询: ...
随机推荐
- Linux的学习日记
CURL 在Ubuntu下尝试安装通过包安装Node.js的时候有这样一种安装方法, 那么有必要学学CURL的知识了. curl是利用URL语法在命令行方式下工作的开源文件传输工具.它被广泛应用在Un ...
- 关于Wireshark "The NPF driver isn’t running……"解决办法
启动Wireshark软件时出现了如下图所示的错误,就搜索了一下解决方法,特总结如下: 这个错误是因为没有开启NPF服务造成的.简要说一下NPF吧. NPF即网 络数据包过滤器(Netgroup Pa ...
- excel出现错误1327 无效的驱动器
错误描述:错误1327 无效的驱动器 错误程序:excel 2003 这是office安装源的位置被移动造 成的的,大部分时候安装时可能使用了移动硬盘或者在安装后调整了盘符就会造成这个问题.官方的 ...
- Alpha阶段第四次Scrum Meeting
情况简述 Alpha阶段第四次Scrum Meeting 敏捷开发起始时间 2016/10/25 00:00 敏捷开发终止时间 2016/10/26 00:00 会议基本内容摘要 做出了将网络通讯接口 ...
- TP-LINK WR941 DD-WRT刷回OpenWRT及OpenWRT刷回原厂固件
1.DD-Wrt 刷回 OpenWrt A.从官网下载固件: root@TL-DDWRT:/tmp# wget http://downloads.openwrt.org/barrier_breaker ...
- SQL case
case when Value='1' then 'True' else 'False' end as 'Result'
- SDL鼠标事件
鼠标事件有这么多种,手柄的可以忽视,Sdl.SDL_KEYDOWN,Sdl.SDL_KEYUP,Sdl.SDL_MOUSEMOTION,Sdl.SDL_MOUSEBUTTONDOWN,Sdl.SDL_ ...
- html5 新选择器 querySelector querySelectorAll
querySelector 返回满足条件的单个元素 使用实例 HTML <div id="main">主体布局</div> JS var main =doc ...
- PHP cookie
PHP Cookie cookie 常用于识别用户. Cookie 是什么? cookie 常用于识别用户.cookie 是一种服务器留在用户计算机上的小文件.每当同一台计算机通过浏览器请求页面时,这 ...
- Android开发-取消程序标题栏或自定义标题栏
注:本文由Colin撰写,版权所有!转载请注明原文地址,谢谢合作! 在Android开发中,跟据需要我们有时候需要自定义应用程序的标题栏或者取消程序的标题栏,下面本菜鸟在此记录与分享一下自己使用的方法 ...