C#入门(2)
C#入门(2)
Exception
基本异常的核心成员:
System.Exception Property | Meaning |
---|---|
Data | read-only,实现了IDirectory接口的一些键值对,来描述额外的或者是程序员定义的信息,默认生成的是空的 |
HelpLink | 一个指向帮助文档或者站点的URL,get or set |
InnerException | read-only,给出引发当前异常信息的异常,之前的异常通常是通过构造函数的参数传递的,不是virtual的 |
Message | read-only,给出error的信息,该信息也是通过构造函数的参数传递的 |
Source | 给出引发异常的程序集或者对象的信息,get or set |
StackTrace | read-only,给出异常信息的传递链 |
TargetSite | read-only,给出引发异常的方法的具体信息 |
定义自己的异常类,必须继承自System.Exception/System.ApplicationException,最好都以Exception结尾,这样比较符合.Net的命名习惯.
继承得到的子类可以将例如string类型的值,传递给父类的Message属性,仅需要在子类的构造函数中将string类对应的值传入到父类base的构造函数中,因为父类的构造函数中有三个特殊的,一个对应string的Message,一个对应Exception的inner exception,还有一个对应自己定义类型的序列化的类型.
[Serializable]
public class CarIsDeadException : ApplicationException
{
public CarIsDeadException() { }
public CarIsDeadException(string message) : base( message ) { }
public CarIsDeadException(string message,
System.Exception inner)
: base( message, inner ) { }
protected CarIsDeadException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
: base( info, context ) { }
}
// Any additional custom properties, constructors and data members...
标准的继承Exception的子类在vs中可以打exception,tab,有代码提示.
多级捕捉也是把最特定性的放前面,一般性的放最后.但是也支持catch后面不接参数,虽然不提倡使用.因为无法得到异常信息.当然在catch中也可以重新throw,但是最好有外层的callback,否则只能由CLR,runtime来接受异常.直接会崩溃.
如果在catch中再次出现异常,如请求了网络或者文件读写,可以在catch嵌套抛出异常,不过还是要在外面接受异常,
catch (CarIsDeadException e)
{
try
{
FileStream fs = File.Open(@"C:\carErrors.txt", FileMode.Open);
...
}
catch (Exception e2)
{
// Throw an exception that records the new exception,
// as well as the message of the first exception.
throw new CarIsDeadException(e.Message, e2);
}
}
注意这里是在原有的异常类型里增加一个参数得到的新的异常抛出,当然外面也应该处理.
Finally是一定要执行的语句.
Interface
.Net中的Interface都带着前缀I.
接口和抽象类的区别:抽象类还是要定义各种构造函数,域类型值,以及部分实现了的函数;但是接口只是定义了多态的函数没有其他以上. 另外,抽象类的继承只能使得子类实现一种功能(单继承,如果此时没有接口继承的话),难以同时拥有多种功能.
接口不能有数据域,即不能有单独的变量,只有方法,但是可以定义属性.同时也可以包含事件和索引.
结构和类都可以实现接口.
运行时得到类是否实现了某个接口可以使用显式地转换,转换为接口类型.(这也解释了为什么Executor类会转变成为ExecutorService,因为这样可以马上被别人看出来这是实现了线程池的类.)
可以使用as和is来判断是不是实现了某种接口,前者不是的话返回一个null,后者则返回一个false.
在使用接口时,如果多个接口共有一个方法,那么在实现时,其实是所有的接口公用了一个方法,应该显式地声明使用的是哪个接口,用"接口.方法"来显式实现.
接口中没有访问限制,所有默认都是public和abstract的.
接口可以多继承,具体的实现决定于程序员,首先所有父类特有的方法都必须继承和实现,而对于两者定义的相同方法,则选择性的实现,如果是要实现两个版本,就和前面显式实现一样.
IEnumerable和IEnumerator接口,前者仅仅有一个方法,返回一个IEnumerator类型的对象.后者是具体实现了选择下一个的功能.
// This interface informs the caller
// that the object's subitems can be enumerated.
public interface IEnumerable
{
IEnumerator GetEnumerator();
}
// This interface allows the caller to
// obtain a container's subitems.
public interface IEnumerator
{
bool MoveNext (); // Advance the internal position of the cursor.
object Current { get;} // Get the current item (read-only property).
void Reset (); // Reset the cursor before the first member.
}
由于实现了IEnumerable和IEnumerator的分离,所以在具体实现的时候只要在Collection中找到实现了IEnumerator的就可以简化实现.使用显式实现接口可以隐藏对象级别的接口实现.
ICloneable和yield关键字:yield和python中类似,返回一个值并且从函数的开头开始执行.所以也可以使用yield和自己显式定义的函数一起实现IEnumerator接口.当深复制的时候注意一件事,如果需要一个不同的GUID(globally unique identifier description),则包含一个System.GUID的对象即可.不过注意更新clone().
ICompareable接口:实现Compareto(),和传统的一样,返回正值,0或者负值,作为判断的标识.
IComparer接口:实现Compare(),可以接受多个参数,主要是接受两个Object,可以任意的按照某一属性比较.现在也可以使用一个静态属性来表示实现某一种接口.如:
public class Car : IComparable
{
//Property to return the PetSortByName
public static ICompare SortByName{
get {return (ICompare) new PetNameCompare();}
}
}
//这里的PetNameCompare是一个类;
// Sorting by pet name made a bit cleaner.
Array.Sort(myAutos, Car.SortByPetName);
Collection和Genetic
在.Net1.0之前没有泛型,因此所有的Collection都需要特殊的自定义函数来添加和减少.常用的几种见下表:
System.Collection Class | Meaning | Key Interface Implementation |
---|---|---|
ArrayList | Represents a dynamically sized collection of objects listed in sequential order. | IList , ICollection, IEnumerable , and ICloneable |
BitArray | Manages a compact array of bit values, which are represented as Booleans, where true indicates that the bit is on (1) and false indicates the bit is off (0). | ICollection, IEnumerable,and ICloneable |
Hashtable | Represents a collection of key/value pairs that are organized based on the hash code of the key. | IDictionary, ICollection,IEnumerable, and ICloneable |
Queue | Represents a standard first-in, first-out (FIFO) collection of objects. | ICollection, IEnumerable, and ICloneable |
SortedList | Represents a collection of key/value pairs that are sorted by the keys and are accessible by key and by index. | IDictionary, ICollection, IEnumerable, and ICloneable |
Stack | A last-in, first-out (LIFO) stack providing push and pop (and peek) functionality. | ICollection, IEnumerable, and ICloneable |
需要注意,现在一般不使用none genetic的类,而应该使用对应的genetic版本.还有一部分是Syetem.Collection.Specialized,也都是no generic其中以下四个用的较多:
System.Collection.Specialized | Meaning |
---|---|
HybridDictionary | 实现了IDictionary接口,在数量小的时候用ListDictionary,大的时候转换成为Hashtable |
ListDictionary | 用单链表连接的字典 |
StringCollection | 大规模使用string时有优化 |
BitVector32 | 32位的内存为一个单元,存储小整型或者是Boolean值 |
需要知道在使用nongenertic时,里面自动装箱和解箱,但是要注意解箱的时候返回的是一个Object类型,需要自己在显式转换.
所以非泛型的容器有两点问题:
- 装箱和解箱的性能问题.
- 类型安全问题,有可能出现不恰当的类型转换.
泛型容器:
仅有class, struct, interface, delegates可以使用泛型,而枚举类型不可以.
常用的泛型容器:
System.Collection.Generic | Support Key Interface | Meaning |
---|---|---|
Dictionary<TKey, TValue> | ICollection<T>,IDictionary<TKey, TValue>,IEnumerable<T> | This represents a generic collection of keys and values. |
LinkedList<T> | ICollection<T>, IEnumerable<T> | This represents a doubly linked list. |
List<T> | ICollection<T>, IEnumerable<T>,IList<T> | This is a dynamically resizable sequential list of items. |
Queue<T> | ICollection (Not a typo! This is the nongeneric collection interface) , IEnumerable<T> | This is a generic implementation of a first-in,first-out (FIFO) list. |
SortedDictionary<TKey,TValue> | ICollection<T>,IDictionary<TKey, TValue>,IEnumerable<T> | This is a generic implementation of a sorted set of key/value pairs. |
SortedSet<T> | ICollection<T>, IEnumerable<T>,ISet<T> | This represents a collection of objects that is maintained in sorted order with no duplication. |
Stack<T> | ICollection (Not a typo! This is the nongeneric collection interface) , IEnumerable<T> | This is a generic implementation of a last-in, first-out (LIFO) list. |
泛型容器的初始化和普通的类型同,也支持大括号的初始化方式,在C++11中叫做初始化列表.也支持在容器内初始化对象,即嵌套的初始化.对于容器的初始化需要注意:
List<T> alist = new List<T>(){.......}
这里的小括号没有也可以,但是为了统一,仍然是先调用初始化函数再初始化列表.统一加().
List,Queue,Stack都没什么特别的,需要注意的是SortSet等有关Sort的需要先写一个类实现ICompare接口,然后将其对象作为参数传递到容器的构造函数中.
System.Collections.ObjectModel:
是一个比较小的命名空间,有一些附加的类型,其中有两个比较重要:
System.Collections.ObjectModel Type | Meaning in Life |
---|---|
ObservableCollection<T> | Represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed. |
ReadOnlyObservableCollection<T> | Represents a read-only version of ObservableCollection<T>. |
这里就是实现了观察者模式,当容器有任何变化时,都会有事件触发,需要实现一个观察者的代理(协议),具体到协议的一部分再介绍.
// Wire up the CollectionChanged event.
people.CollectionChanged += people_CollectionChanged;
其实有很多需要使用泛型的原因还在于需要考虑装箱解箱的效率(不需要堆和栈之间的拷贝),以及函数重载的不足.
泛型容器的构造函数:在泛型中可以使用default关键词,这里就是default就有多重含义.由于泛型中无法得到具体的类型参数的初始值,因此初始值对于数值型是0,对于引用型是null.
// Reset fields to the default value of the
// type parameter.
public void ResetPoint()
{
xPos = default(T);
yPos = default(T);
}
这里的default就保证了得到初始值.
对类型参数的约束:使用where对type进行约束,见下表:
Generic Constraint | Meaning in Life |
---|---|
where T : struct | The type parameter <T> must have System.ValueType in its chain of inheritance (i.e., <T> must be a structure). |
where T : class | The type parameter <T> must not have System.ValueType in its chain of inheritance (i.e., <T> must be a reference type). |
where T : new() | The type parameter <T> must have a default constructor. This is helpful if your generic type must create an instance of the type parameter because you cannot assume you know the format of custom constructors. Note that this constraint must be listed last on a multiconstrained type. |
where T : NameOfBaseClass | The type parameter <T> must be derived from the class specified byNameOfBaseClass. |
where T : NameOfInterface | The type parameter <T> must implement the interface specified by NameOfInterface. You can separate multiple interfaces as a comma-delimited list. |
注意其中的new()必须放在最后.如果有多个Type参数则必须使用多个where语句.
C#入门(2)的更多相关文章
- Angular2入门系列教程7-HTTP(一)-使用Angular2自带的http进行网络请求
上一篇:Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数 感觉这篇不是很好写,因为涉及到网络请求,如果采用真实的网络请求,这个例子大家拿到手估计还要自己写一个web ...
- ABP入门系列(1)——学习Abp框架之实操演练
作为.Net工地搬砖长工一名,一直致力于挖坑(Bug)填坑(Debug),但技术却不见长进.也曾热情于新技术的学习,憧憬过成为技术大拿.从前端到后端,从bootstrap到javascript,从py ...
- Oracle分析函数入门
一.Oracle分析函数入门 分析函数是什么?分析函数是Oracle专门用于解决复杂报表统计需求的功能强大的函数,它可以在数据中进行分组然后计算基于组的某种统计值,并且每一组的每一行都可以返回一个统计 ...
- Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数
上一篇:Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数 之前介绍了简单的路由以及传参,这篇文章我们将要学习复杂一些的路由以及传递其他附加参数.一个好的路由系统可以使我们 ...
- Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数
上一篇:Angular2入门系列教程-服务 上一篇文章我们将Angular2的数据服务分离出来,学习了Angular2的依赖注入,这篇文章我们将要学习Angualr2的路由 为了编写样式方便,我们这篇 ...
- Angular2入门系列教程4-服务
上一篇文章 Angular2入门系列教程-多个组件,主从关系 在编程中,我们通常会将数据提供单独分离出来,以免在编写程序的过程中反复复制粘贴数据请求的代码 Angular2中提供了依赖注入的概念,使得 ...
- wepack+sass+vue 入门教程(三)
十一.安装sass文件转换为css需要的相关依赖包 npm install --save-dev sass-loader style-loader css-loader loader的作用是辅助web ...
- wepack+sass+vue 入门教程(二)
六.新建webpack配置文件 webpack.config.js 文件整体框架内容如下,后续会详细说明每个配置项的配置 webpack.config.js直接放在项目demo目录下 module.e ...
- wepack+sass+vue 入门教程(一)
一.安装node.js node.js是基础,必须先安装.而且最新版的node.js,已经集成了npm. 下载地址 node安装,一路按默认即可. 二.全局安装webpack npm install ...
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
随机推荐
- Linux中如何开启8080端口供外界访问 和开启允许对外访问的端口8000
举例: 开放10000端口的解决步骤如下: 1.修改/etc/sysconfig/iptables文件,增加如下一行: -A INPUT -m state --state NEW -m tcp -p ...
- ShutdownHook作用
源地址:http://kim-miao.iteye.com/blog/1662550 void java.lang.Runtime.addShutdownHook(Thread hook) 该方法用来 ...
- java的环境变量classpath中加点号 ‘.’ 的作用
java的环境变量classpath中加点号 ‘.’ 的作用 “.”表示当前目录,就是编译或者执行程序时,你的.class文件所在的目录: 当找.class文件时,先去“.”路径下找,找不到的话,在去 ...
- Flutter实战视频-移动电商-61.购物车_商品数量的加减操作
61.购物车_商品数量的加减操作 provide/cart.dart pages/cart_page/cart_count.dart 先引入provide和cartProvide 定义接收一个item ...
- 28.Docker介绍与目录
快速的部署和启动 docker的启动是毫秒级的.一分钟可移动几百个上千个docker的容器 docker和虚拟机的区别 虚拟机在里面独立运行完整的操作系统.资源上时间上都需要多. docker容器级别 ...
- Python3.6 字典的内置方法
1.dict.clear(self) 删除字典内所有元素 2.dict.copy(self) 返回一个字典的浅复制,拷贝父对象,不会拷贝对象的内部的子对象 3.dict.fromkeys(self, ...
- Bootstrap表格分页(二)
本文使用Bootstrap-table来对表格进行分页,关于Bootstrap-table以及下载插件包请点击官网:http://bootstrap-table.wenzhixin.net.cn 首先 ...
- 在linux上部署tomcat服务
在linux上部署tomcat 1.安装JDK 2.下载tomcat http://tomcat.apache.org/download-70.cgi 3.上传到服务器,并解压 4.上传war包或者已 ...
- Lightoj1122 【数位DP】
题意: 给你m个数,让你在里面挑n个组合,保证位数相差不超过2,求能够组合多少种情况: 思路: dp[i][j]代表第i个结尾为j的方案数. #include<bits/stdc++.h> ...
- 强大的在线web编辑器UEditor
UEditor是由百度web前端研发部开发所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码. UEditor在线演示地址:http://u ...