一、c#中的特殊数据类型

C#中特殊数据类型有class类型、结构类型、数组类型、枚举类型、集合类型、委托类型、事件、Lambda表达式、接口类型。

1、class类型
1.1类定义
class Student : person//继承
{
//默认构造函数,vs IDE中输入ator+tab两下可自动生成构造函数代码段
public Student()
{
//给字段赋值等初始化操作
}
//自定义构造函数,b为可选参数
public Student(int a, string b = )
{
//初始化操作
}
public Student(int a)//自定义构造函数
{
//初始化操作
}
//静态构造函数-安全的给静态字段赋值且只能被定义一个(采用普通构造函数每次实例化类对象时静态字段的值会被重置)
static Student{aCuu=0.04}//不允许访问修饰符,不接受参数 //static关键字用来定义静态成员,这些成员只能通过类级别而不是对象引用调用。
//static关键字,静态字段由所有类实例共享
public static double aCuu = 0.04;
public string petName;//字段,最好定义成私有的以保护
public void Name(string name) { }---方法 } //静态类-只包含静态成员,不能够使用new(分配新内存)关键字来创建类对象-适合做工具类
static class Student { }
1.2访问修饰符

类型成员隐式私有的,而类是隐式内部的。

private、protected、protected internal访问修饰符可以应用到嵌套类型上,非嵌套类型只能用public internal修饰符定义。

public 可以从对象、派生类、外部其它程序集访问
private 定义类访问
protected 定义类及子类可以访问,外部类无法通过点操作符访问
internal 只能在当前程序集中访问
protected internal 在定义该项的程序集、类及派生类中可用
1.3 this 关键字

提供对当前类实例的访问。

串联构造函数,使类更容易维护和简明。

    class Motorcycle
{
public int driverIntensity;
public string drivername;
//构造函数
public Motorcycle(){}
public Motorcycle(int intensity) : this(intensity, "") { }
public Motorcycle(string name):this(,name) { }
//所有工作的主构造函数
public Motorcycle(int intensity,string name)
{
//操作
}
}
2、结构类型

结构类型可以看成是轻量级的类类型,但是不能像类一样继承

  struct point
{
//字段
public int x;
//方法
public void Increment()
{
}
} //创建结构变量
point p1;
p1.x = ;//需要为每一个共有字段成员赋值
point p2 = new point();
3、数组类型

一组相同类型的数据点:int[] myInt=new int[3]

int[] myInt=new int[3]{1,2,3}  #初始化

3.1 特殊数组
隐式数组 var a=new[]{1,2,3}
object数组 object[] myob=new[3]{1,"string",new DateTime(2017,8,28)}
多维数组 int[,] myArray=new int[6,6]
4、枚举类型

System.Enum类中包含有一些对枚举类型操作的方法

 enum Emptype:Byte
{
manager=,//=0,可任意,可不连续
student,
teancher
} Emptype ee = Emptype.manager;
Enum.GetUnderlyingType(ee.GetType());//返回枚举类型值的数据类型
Console.WriteLine(ee.ToString());//获取枚举名字
Console.WriteLine((Byte)ee);//根据底层类型强制转换获取其数值 Array enumData = Enum.GetValues(ee.GetType());//获取所有枚举值
Console.WriteLine("this enum has {0} nums:", enumData.Length);
Console.WriteLine("name{0};value{1}", enumData.GetValue());
5、集合类型-数据容器

System.Collections与System.Collection.Generic命名空间

  简单数组通常是固定大小的,而集合类本身的尺寸是动态的,类似于python中的list类型,很多集合提供了更强的类型安全,进行了高度优化,可以以内存高效的方式处理所包含的数据。

  集合可划分为两大种类:非泛型集合和泛型集合

5.1泛型集合System.Collections常用类
ArrrayList 动态大小对象集合,对象按顺序列出 Ilist/Icollection/IEnumerable/ICloneable
BitArray 管理位值的简单数组,位值bool类型 ICollection/IEnumerable/ICloneable
Hashtable 表示键值对的集合 IDictionary/Icollection/IEnumerable/ICloneable
Queue FIFO队列 ICollection/IEnumerable/ICloneable
SortedList 键值对集合按键排序 IDictionary/Icollection/IEnumerable/ICloneable
Stack 后进先出 ICollection/IEnumerable/ICloneable

System.Collections中类所支持的关键接口

ICollection 为所有非泛型集合定义基本特性(大小、枚举、线程安全)
ICloneable 允许实现它的对象向调用者返回它的副本
IDictionary 非泛型集合使用键值对表示其内容
IEnumerable 返回实现了IEnumerable接口的对象
IEnumerator 允许子类型以foreach形式迭代
IList 为顺序列表中的对象提供添加、移除和索引项的行为

示例代码:

class Program
{
static void Main(string[] args)
{
ArrayList list = new ArrayList();
//集合:很多数据的一个集合
//数组:长度不可变、类型单一
list.Add(true);
list.Add();
list.Add();
list.Add("张三");
Person person = new Person();
list.Add(person);
list.Add(new int[] { , , });
list.AddRange(list);
list.AddRange(new int[] { , });//此种方法可以直接输出
for(int i=; i<list.Count; i++)
{
if(list[i] is Person )
{
((Person)list[i]).SayKello();
}
else if(list[i] is int[])
{
for(int j=;j<((int[])list[i]).Length;j++)
{
Console.WriteLine(((int[])list[i])[j]);
}
} //麻烦
else
{
Console.WriteLine(list[i]);
} }
Console.ReadKey();
//List元素打印出来的是所在类对应的命名空间
} class Person
{
public void SayKello()
{
Console.Write("你好"+"\r\n");
}
} }
//其他类的用法类似,有相应的文档
HashTable示例:
  static void Main(string[] args)
{ //键值对集合类似于字典,根据键去找值,就像根据拼音去找汉字
Hashtable ht = new Hashtable();
ht.Add(,"张三");
ht.Add(,"小王");
ht.Add(false,"错误的");
for (int i = ; i < ht.Count; i++)
{
object a = ht[i];
Console.WriteLine(a);
}
//不能全部显示(0和false)
Console.ReadKey();
Console.WriteLine(ht[false]); //也可以采用foreach循环遍历
foreach (var item in ht.Keys)
{
//C#是一门强类型语言:代码中每一个变量类型必须有明确的定义
//int n = 15;
//string ste = "sfdd";
//bool n5 = true;
//double n6 = 230.23;
//Console.WriteLine(n.GetType());
//Console.WriteLine(ste.GetType());
//Console.WriteLine(n5.GetType());
//Console.WriteLine(n6.GetType());
//Console.ReadKey(); //根据值推断出类型
//var n = 15;
//var ste = "sfdd";
//var n5 = true;
//var n6 = 230.23; //Console.WriteLine(n.GetType());
//Console.WriteLine(ste.GetType());
//Console.WriteLine(n5.GetType());
//Console.WriteLine(n6.GetType());
//Console.ReadKey();
//var input; 声明var变量的时候必需给它赋值
//input = "人民";
Console.WriteLine(ht[item]);
}
Console.ReadKey(); }
5.2非泛型集合

  相比较于泛型集合,非泛型集合更为常用,经典的泛型集合常常存在如下问题:

1)频繁的装箱拆箱操作,当数据量过大时会降低程序效率:

  .NET包含一个特殊的Object类,可以接受任意的数据类型的值,当所传递或所赋值的类型不是一个特定的数据类型时,object类就提供了一种传递参数和赋值的通用方法。赋给object的值必须作为引用类型,并存放砸托管堆中,简言之装箱就是值类型转换为引用类型;拆箱就是引用类型转换为值类型。

  值类型:包括原类型(Sbyte、Byte、Short、Ushort、Int、Uint、Long、Ulong、Char、Float、Double、Bool、Decimal)、枚举 (enum) 、结构 (struct)。

  引用类型:包括类、数组、接口、委托、字符串等

  一下特殊情况需要注意:

隐式转换总会成功的情况 显式引用转换可能会抛出异常的情况
从派生类到基类 从基类到派生类
从派生接口到基接口 从接口到接口(基接口到派生接口或者俩接口没有关系)
从类到接口(该类实现了接口) 从接口到类(该类实现了该接口或该类未封闭)
从Null到任何类 从类到接口(该类未实现该接口且该类未封闭)
 class Program
{
int a = ;
object ob = a;//装箱操作
int b = (int)ob;//拆箱操作
}

2)类型安全问题,所有的类型都可以转换成object类,在特定的情况下存在类型安全问题。

5.3泛型集合

只有类、结构、接口和委托可以使用泛型,枚举类型不可以。

1)System.Collection.Generic命名空间

2)初始化语法

 class Point
{
int x;
int y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
} }
class Program
{
static void Main(string[] args)
{
List<Point> myOfpoint = new List<Point>
{
new Point(,),
new Point(,)
};
}
}

3)List<T>类

常见用法见:http://www.cnblogs.com/AdaLoong/p/5528917.html

4)Stack<T>类---后进先出

包含Push和Pop方法,可以向栈中压入数据或弹出数据,在观察栈时得到的永远是栈顶对象,可以通过调用peek()来显示。

http://www.cnblogs.com/deom/p/5349317.html

5)Queue<T>类---先进先出

http://www.cnblogs.com/jiahuafu/archive/2013/01/05/2845640.html

Dequeue()---移除并返回开始出的对象;

Enqueue()---在末未添加一对象;

peek()---返回开始出的对象但是不移除。

6)SortedSet<T>类---自动排序

必须通知SortedSet<T>类按照何种方式排序,可以向其构造函数传递一个实现了IComparer<T>泛型接口的参数,比如一个实现了该泛型接口的类。

http://blog.sina.com.cn/s/blog_621e24e20100zqmq.html

class sortByage:IComparer<Person>
{
public int Compare(Person firstperson,Person secondperson)
{
if (firstperson.age > secondperson.age)
return ;
if (firstperson.age < secondperson.age)
return -;
else
return ;
}
}
class Person
{
string firstname;
string lastname;
public int age;
public Person(string firstname,string lastname,int age)
{
this.firstname = firstname;
this.lastname = lastname;
this.age = age;
}
}
static void Main(string[] args)
{
SortedSet<Person> mysortedOfperson = new SortedSet<Person>(new sortByage())
{
new Person("wangming","zhang",),
new Person("xiaogang","wang",),
new Person("xiaohong","li",)
};
//按照年龄排序
foreach (Person p in mysortedOfperson)
{
Console.WriteLine(p.age);
}
Console.ReadKey();
}

7)System.Collections.ObjectModel命名空间

该命名空间也是以泛型为核心

两个比较有用的类

ObservableCollection<T> 表示能在添加、移除项或者刷新整个列表时提供通知的动态数据集合
ReadOnltObservableCollection<T> 表示ObservableCollection<T>的只读版本

  ObservableCollection<T>与List<T>具有相同的核心接口,不同的是ObservableCollection<T>实现了名为CollectionChanged的事件,该事件在添加、移除项或者刷新整个列表时触发。

  CollectionChanged定义为委托,该委托可以调用一类方法(第一个参数为object,第二个参数为NotifyCollectionChangedEventArgs)。

  

class Program
{
static void Main(string[] args)
{
ObservableCollection<Person> mysortedOfperson = new ObservableCollection<Person>()
{
new Person("wangming","zhang",),
new Person("xiaogang","wang",),
new Person("xiaohong","li",)
};
//按照年龄排序
//绑定collentionchanged事件
mysortedOfperson.CollectionChanged += people_collentionchanged;
mysortedOfperson.Add(new Person("jfoda", "ad", ));
Console.ReadKey(); }
static void people_collentionchanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
//触发事件的行为是什么
Console.WriteLine("Action for this event:{0}", e.Action);
if(e.Action==System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
Console.WriteLine("here are the new item:");
foreach (Person p in e.NewItems)
{
Console.WriteLine(p.ToString());
}
}
} }
class Person
{
string firstname;
string lastname;
public int age;
public Person(string firstname,string lastname,int age)
{
this.firstname = firstname;
this.lastname = lastname;
this.age = age;
}
}
6、委托类型delegate

委托类型用来定义和响应应用程序中的回调,使用回调程序员可以使用一个函数返回报告给程序中的另一个函数,使用这种方法,windows开发者可以可以处理按钮单击、鼠标移动、菜单选择以及内存中两个实体的双向通信。本质上委托是个类型安全的对象,它指向一个以后会被调用的方法(或者多个方法),可以不用手工创建一个thread对象去条用其它thread上的方法,委托类型有三个重要的信息:

1)它所调用的方法和名称

2)该方法的参数(可选)

3)该方法的返回值类型(可选)

6.1、委托类型的定义

public delegate int BinaryOp(int x,int y)

使用delegate关键字,就间接创建了一个类,这个类是“MulticastDelegate”,下表显示了所有委托对象都有的核心成员。

例1:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace 委托简例
{
public delegate int BinaryOp(int x, int y);
//创建一个包含委托指向方法的类
public class SimpleMath
{
public int Add(int x, int y)
{
return x + y;
}
}
class Program
{
//显示委托对象所维护的方法名称及对应的类名称
static void DisplayDelegateInfo(Delegate delObj)
{
//输出委托调用列表中每个成员的名称
foreach (Delegate d in delObj.GetInvocationList())
{
Console.WriteLine("Method name:{0}", d.Method);
Console.WriteLine("Type name:{0}", d.Target);
}
Console.ReadKey();
}
static void Main(string[] args)
{
//实例化一个委托对象
BinaryOp bp = new BinaryOp(new SimpleMath().Add);//指向的是非静态方法要生成实例
//BinaryOp bp = new BinaryOp(SimpleMath.Add);//指向的是静态方法则不需要,只需给出内存地址即可
Console.WriteLine("10+10={0}", bp(, ));
Console.ReadKey();
DisplayDelegateInfo(bp);
}
}
}
例2
//声明委托
public delegate void Mydel();
public delegate void Mydel2(int num1, int num2);
public delegate string Mydel3(string s);
//声明委托用于演示匿名方法
public delegate string ProcessString(string S);
class Program
{
static void Main(string[] args)
{
TestDel t = new TestDel();
#region 简单实例化委托与调用委托
Console.WriteLine("------以下是简单使用委托演示----");
t.MyMethod(); //实例化委托,用一个方法实例化
//该方法签名要与委托签名一致
Mydel del0 = new Mydel(t.MyMethod);
//调用委托
del0();
//另一种实例化方法
Mydel del1 = t.MyMethod;
del1(); //用静态方法进行实例化
del1 = TestDel.MyStaticMethod;
del1();
//以下代码效果相同
//类TestDel中重载了多种MyMethod方法,委托自动识别一致参数类型的方法
Mydel2 del2 = new Mydel2(t.MyMethod);
del2(,);
Mydel2 del121 = t.MyMethod;
del121(, );
Mydel3 del3 = new Mydel3(t.MyMethod);
del3("adfa");
#endregion #region 匿名实例化weit
Console.WriteLine("-----以下是匿名调用委托--");
//用匿名方法实例化委托,不需函数名,直接就是参数+函数体
ProcessString p = delegate(string inputString)
{
return inputString.ToUpper();
};
//通过委托调用匿名方法
Console.WriteLine(p("wefewe"));
#endregion #region 委托多播演示
Console.WriteLine("---------以下是多播演示--------");
Mydel mydel1 = t.MyMethod;
Mydel mydel2 = t.MyMethod2;
Mydel mydel3 = TestDel.MyMethod3;
//委托类型必须一致才能相加
Mydel allmydel = mydel1 + mydel2 + mydel3;
allmydel();
allmydel -= mydel3;
allmydel();
#endregion #region 委托作为参数演示
Console.WriteLine("-------以下委托作为参数演示--------");
Mydel3 paraMydel3 = t.MyMethod;
TestDel.MyParamMethod("aaa", paraMydel3);
#endregion #region 委托作为返回值
Console.WriteLine("----以下委托作为返回值演示-----");
//returnMydel指向ReturnMyMethod的返回值
Mydel3 returnMydel = t.ReturnMyMethod();
//returnMydel1指向t.MyMethod
Mydel3 returnMydel1 = t.MyMethod;
Console.WriteLine(returnMydel("sssssss"));
#endregion } }
public class TestDel
{
#region 普通方法
public static void MyStaticMethod()
{
Console.WriteLine("My Static Method");
}
public void MyMethod()
{
Console.WriteLine("MyMethod");
}
public void MyMethod2()
{
Console.WriteLine("My Method 22222222222");
}
public static void MyMethod3()
{
Console.WriteLine("My Method 3333333333333");
}
public void MyMethod(int num1, int num2)
{
Console.WriteLine(num1 + num2);
}
public string MyMethod(string s)
{
return s.ToUpper();
}
#endregion
/// <summary>
/// 委托作为方法参数
/// </summary>
/// <param name="s"></param>
/// <param name="del3"></param>
public static void MyParamMethod(string s, Mydel3 del3)
{
Console.WriteLine(del3(s));
}
/// <summary>
/// 委托作为返回值
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public Mydel3 ReturnMyMethod()
{
///返回符合委托规范的方法
return MyMethod;
} }
6.2使用委托发送对象通知状态

类似于通过回调函数返回状态信息

namespace 委托通知
{
//使用委托来定义car类,他可以通知外部实体当前引擎状态
/// <summary>
/// (1)定义将通知发送给调用者的委托类型
/// (2)声明car类中每个委托类型的成员变量
/// (3)在car上创建副主函数使得调用者能指定由委托成员变量保存的方法
/// (4)修改Accelerate()方法以在适当的情形下调用委托的调用列表
/// </summary>
public class Car
{
//内部状态数据
public int CurentSpeed;
public int MaxSpeed;
public string name;
//汽车能不能用
private bool carIsdead;
//类构造函数
public Car() { }
public Car(string name,int currentspeed,int maxspeed=)
{
this.name = name;
this.CurentSpeed = currentspeed;
this.MaxSpeed = maxspeed;
}
//定义委托类型
public delegate void CarEngineHandler(string msdForCar);
//定义每个委托类型的成员变量
private CarEngineHandler listOfhandlers;
//向调用者添加注册函数
public void RegisterWithCarEngine(CarEngineHandler methodTocall)
{
if (listOfhandlers == null)
listOfhandlers = methodTocall;
else
listOfhandlers += methodTocall;//支持多路广播
}
//实现Accelerate()方法
public void Accelerate(int delta)
{
if(carIsdead)
{
if(listOfhandlers!=null)
{
listOfhandlers("sorry,this car is dead");
}
}
else
{
CurentSpeed += delta;
//不能超过最大速度
if(==(MaxSpeed-CurentSpeed) && listOfhandlers != null)
{
listOfhandlers("this speed is nearly to the maxspeed");
}
if (CurentSpeed > MaxSpeed)
{
carIsdead = true;
}
else
Console.WriteLine("current speed:{0}", CurentSpeed);
}
}
}
class Program
{
static void Main(string[] args)
{
//首先创建一个car对象
Car mycar = new Car("xiaowang",);
//现在告诉汽车他想要向我们发送信息是应该调用哪个方法
mycar.RegisterWithCarEngine(new Car.CarEngineHandler(OnCarEngineEvent));
//方法组转换语句---传递与委托类型一致的函数
//mycar.RegisterWithCarEngine(CallMeHere);
//加速,触发事件
Console.WriteLine("*******speed up********");
for(int i=;i<;i++)
{
mycar.Accelerate();
Console.ReadKey();
}
//要传入事件的方法
}
public static void OnCarEngineEvent(string msg)
{
Console.WriteLine("feedback information:{0}", msg);
}
static void CallMeHere(string msg)
{
Console.WriteLine("feedback information:{0}", msg);
}
}
}
6.2实现多路广播---见6.1
6.3泛型委托

泛型参数

public delegate void MyDelegate<T>(T mycan);-------对应一类函数

泛型Action<>和Func<>委托------框架内置的委托

泛型Action:可以指向多至16个参数并返回void的方法,需要制定各个参数的具体类型。

Func<>委托:可以指向多至16个参数并且具有自定义返回值。

Func<int,int,int> functarget=new Func<int,int,int>(Add);

Add中本有两个参数,Func<int,int,int>最后一个参数是返回值。

7、事件

event关键字在变已处理的时候,它会自动的提供注册和注销方法以及任何必要的委托类型成员变量,这些成员变量是私有的,不能从出发事件的对象访问。

定义事件:

1)定义委托类型----事件触发时要调用的方法;

2)用相关委托声明这个事件----使用event关键字。

namespace 委托通知
{
//使用委托来定义car类,他可以通知外部实体当前引擎状态
/// <summary>
/// (1)定义将通知发送给调用者的委托类型
/// (2)声明car类中每个委托类型的成员变量
/// (3)在car上创建副主函数使得调用者能指定由委托成员变量保存的方法
/// (4)修改Accelerate()方法以在适当的情形下调用委托的调用列表
/// </summary>
namespace 委托通知
{
//使用委托来定义car类,他可以通知外部实体当前引擎状态
/// <summary>
/// (1)定义将通知发送给调用者的委托类型
/// (2)声明car类中每个委托类型的成员变量
/// (3)在car上创建副主函数使得调用者能指定由委托成员变量保存的方法
/// (4)修改Accelerate()方法以在适当的情形下调用委托的调用列表
/// </summary>
public class Car
{
//内部状态数据
public int CurentSpeed;
public int MaxSpeed;
public string name;
//汽车能不能用
private bool carIsdead;
//类构造函数
public Car() { }
public Car(string name, int currentspeed, int maxspeed = )
{
this.name = name;
this.CurentSpeed = currentspeed;
this.MaxSpeed = maxspeed;
}
//定义委托类型
public delegate void CarEngineHandler(string msdForCar);
//定义每个委托类型的成员变量
private CarEngineHandler listOfhandlers;
//向调用者添加注册函数
public void RegisterWithCarEngine(CarEngineHandler methodTocall)
{
if (listOfhandlers == null)
listOfhandlers = methodTocall;
else
listOfhandlers += methodTocall;//支持多路广播
}
//实现Accelerate()方法
public void Accelerate(int delta)
{
if (carIsdead)
{
if (listOfhandlers != null)
{
listOfhandlers("sorry,this car is dead");
}
}
else
{
CurentSpeed += delta;
//不能超过最大速度
if ( == (MaxSpeed - CurentSpeed) && listOfhandlers != null)
{
listOfhandlers("this speed is nearly to the maxspeed");
}
if (CurentSpeed > MaxSpeed)
{
carIsdead = true;
}
else
Console.WriteLine("current speed:{0}", CurentSpeed);
}
}
}
public class newCar
{
//内部状态数据
public int CurentSpeed;
public int MaxSpeed;
public string name;
//汽车能不能用
private bool carIsdead;
//类构造函数
public newCar() { }
public newCar(string name, int currentspeed, int maxspeed = )
{
this.name = name;
this.CurentSpeed = currentspeed;
this.MaxSpeed = maxspeed;
}
//定义委托用来与car的时间协作
public delegate void CarEngineNewHandles(string msg);
//汽车可以发送的事件
public event CarEngineNewHandles Exploded;
public event CarEngineNewHandles AbouttoBlow; public void NewAccelerate(int delta)
{
if (carIsdead)
{
if (Exploded != null)
{
Exploded("sorry,this car is dead");
}
}
else
{
CurentSpeed += delta;
//不能超过最大速度
if ( == (MaxSpeed - CurentSpeed) && AbouttoBlow != null)
{
AbouttoBlow("this speed is nearly to the maxspeed");
}
if (CurentSpeed > MaxSpeed)
{
carIsdead = true;
}
else
Console.WriteLine("current speed:{0}", CurentSpeed);
}
}
}
class Program
{
static void Main(string[] args)
{
//////////////////////////////////////////////////////////////////////////使用委托回调
//首先创建一个car对象
Car mycar = new Car("xiaowang", );
//现在告诉汽车他想要向我们发送信息是应该调用哪个方法
mycar.RegisterWithCarEngine(new Car.CarEngineHandler(OnCarEngineEvent));
//方法组转换的---传递与委托类型一致的函数
//mycar.RegisterWithCarEngine(CallMeHere);
//加速,触发事件
Console.WriteLine("*******speed up********");
for (int i = ; i < ; i++)
{
mycar.Accelerate();
Console.ReadKey();
} ////////////////////////////////////////////////////////////////////////// 使用事件回调 //调用者监听传入的事件
///先要使用+=h和-=注册和删除事件
newCar c1 = new newCar("wangming", );
//注册事件处理程序
c1.AbouttoBlow += new newCar.CarEngineNewHandles(CarIsAboutToBlow);
c1.AbouttoBlow += new newCar.CarEngineNewHandles(CarIsAmostAboutToBlow); newCar.CarEngineNewHandles d = new newCar.CarEngineNewHandles(OnCarEngineEvent);
c1.Exploded += d; for (int i = ; i < ; i++)
{
c1.NewAccelerate();
Console.ReadLine();
} ///使用方法组转换简化
newCar c2 = new newCar("wangming", );
//注册事件处理程序
c2.AbouttoBlow += CarIsAboutToBlow;
c2.AbouttoBlow += CarIsAmostAboutToBlow;
newCar.CarEngineNewHandles d2 = new newCar.CarEngineNewHandles(OnCarEngineEvent);
c2.Exploded += d2; } public static void OnCarEngineEvent(string msg)
{
Console.WriteLine("feedback information:{0}", msg);
}
public static void CarIsAboutToBlow(string msg)
{
Console.WriteLine("car is about to blow");
}
public static void CarIsAmostAboutToBlow(string msg)
{
Console.WriteLine("car is about to blow");
}
} } public class newCar
{
//内部状态数据
public int CurentSpeed;
public int MaxSpeed;
public string name;
//汽车能不能用
private bool carIsdead;
//类构造函数
public newCar() { }
public newCar(string name, int currentspeed, int maxspeed = )
{
this.name = name;
this.CurentSpeed = currentspeed;
this.MaxSpeed = maxspeed;
}
//定义委托用来与car的时间协作
public delegate void CarEngineNewHandles(string msg);
//汽车可以发送的事件
public event CarEngineNewHandles Exploded;
public event CarEngineNewHandles AbouttoBlow; public void NewAccelerate(int delta)
{
if (carIsdead)
{
if (Exploded != null)
{
Exploded("sorry,this car is dead");
}
}
else
{
CurentSpeed += delta;
//不能超过最大速度
if ( == (MaxSpeed - CurentSpeed) && AbouttoBlow != null)
{
AbouttoBlow("this speed is nearly to the maxspeed");
}
if (CurentSpeed > MaxSpeed)
{
carIsdead = true;
}
else
Console.WriteLine("current speed:{0}", CurentSpeed);
}
}
}
class Program
{
static void Main(string[] args)
{
//////////////////////////////////////////////////////////////////////////使用委托回调
//首先创建一个car对象
Car mycar = new Car("xiaowang", );
//现在告诉汽车他想要向我们发送信息是应该调用哪个方法
mycar.RegisterWithCarEngine(new Car.CarEngineHandler(OnCarEngineEvent));
//方法组转换的---传递与委托类型一致的函数
//mycar.RegisterWithCarEngine(CallMeHere);
//加速,触发事件
Console.WriteLine("*******speed up********");
for (int i = ; i < ; i++)
{
mycar.Accelerate();
Console.ReadKey();
} ////////////////////////////////////////////////////////////////////////// 使用事件回调 //调用者监听传入的事件
///先要使用+=h和-=注册和删除事件
newCar c1 = new newCar("wangming", );
//注册事件处理程序
c1.AbouttoBlow += new newCar.CarEngineNewHandles(CarIsAboutToBlow);
c1.AbouttoBlow += new newCar.CarEngineNewHandles(CarIsAmostAboutToBlow); newCar.CarEngineNewHandles d = new newCar.CarEngineNewHandles(OnCarEngineEvent);
c1.Exploded += d; for (int i = ; i < ; i++)
{
c1.NewAccelerate();
Console.ReadLine();
} ///使用方法组转换简化
newCar c2 = new newCar("wangming", );
//注册事件处理程序
c2.AbouttoBlow += CarIsAboutToBlow;
c2.AbouttoBlow += CarIsAmostAboutToBlow;
newCar.CarEngineNewHandles d2 = new newCar.CarEngineNewHandles(OnCarEngineEvent);
c2.Exploded += d2; } public static void OnCarEngineEvent(string msg)
{
Console.WriteLine("feedback information:{0}", msg);
}
public static void CarIsAboutToBlow(string msg)
{
Console.WriteLine("car is about to blow");
}
public static void CarIsAmostAboutToBlow(string msg)
{
Console.WriteLine("car is about to blow");
}
} }

从上面的例子也可以看出,手工定义一个委托对象调用的方法显的有点繁琐,不会很受欢迎,可以在实践注册时之间将一个委托与一段代码相关联-----------匿名方法。

示例代码入下:

            //注册事件处理程序作为匿名方法
c3.AbouttoBlow += delegate (string msg)
{
Console.WriteLine("匿名委托返回消息{0}", msg);
Console.ReadKey();
};
c3.Exploded += delegate (string msg)
{
Console.WriteLine("feedback information:{0}", msg);
Console.ReadLine();
};
for (int i = ; i < ; i++)
{
c3.NewAccelerate();
}
8、Lambda表达式

lambda表达式本质上是用更简单的方法写匿名方法,首先定义一个参数列表,"=>"标记紧随其后,然后就是处理这些参数的语句。

ArgumentsToProcess=>StatementsToProcessThem;参数类型可以是显式的也可以是隐式的。

namespace Lambda表达式
{
class Program
{
static void Main(string[] args)
{
TraditionalDelegateSyntax();
} static void TraditionalDelegateSyntax()
{
//创建整数列表
List<int> list = new List<int>();
list.AddRange(new int[] { , , , , , }); ////使用传统委托方法调用FindAll()
//Predicate<int> callback = new Predicate<int>(IsEvenNumber);
//List<int> evennumbers = list.FindAll(callback);
//foreach (int evennum in evennumbers)
//{
// Console.WriteLine("{0}\t", evennum);
//}
//Console.ReadKey();
//////////////////////////////////////////////////////////////////////////
//采用匿名方法
//List<int> evennumbers = list.FindAll(delegate (int num)
//{
// return (num % 2 == 0);
//});
//foreach (int evennum in evennumbers)
//{
// Console.WriteLine("{0}\t", evennum);
//} //////////////////////////////////////////////////////////////////////////
//采用Lamada表达式
List<int> evennumbers = list.FindAll(num=>(num%)==);
//运行时被编译成了上述匿名方法
foreach (int evennum in evennumbers)
{
Console.WriteLine("{0}\t", evennum);
}
Console.ReadKey(); }
static bool IsEvenNumber(int num)
{
//这是个偶数
return (num % == );
}
}
}
9、接口

接口是一组抽象成员的命名集合,由接口定义的某个特定成员依赖于它所模拟的确切行为。.NET基础库中提供了几百个预定义的接口类型,由各种类和结构实现。 与抽象类不同,接口只能包含抽象成员,由于C#中类不支持多重继承,一个父类定义的抽象成员只能被其派生类继承,但是大型系统中开发除了Object之外没有公共父类的多个层次结构很普遍,这样就不能配置多层次结构支持相同的多态接口,接口类型解决了这一问题,它可以被任何层次结构。任何命名空间或任何程序集中的任何类或结构来实现,这样接口就有了较高的多态性。

1)不能向类和结构一样分配类型:

Ipointy p=new Ipointy()

2)实现接口是个要"要么全要要么全部不要”的命题,即支持类型无法选择实现哪些成员。

    interface IPoint
{
//接口定义
//1)不指定访问修饰符(默认隐式共有、抽象)
//2)不能实现
// byte GetNumofPoint(); //只读属性
byte Points{ get; } }
//实现接口时要么全要,要么全不要
class Triangle:Object,IPoint
{ //...
public byte Points
{
get { return ; }
}
} class Program
{
static void Main(string[] args)
{
//在对象级别调用接口成员
Triangle triangle = new Triangle();
Console.WriteLine(triangle.Points);
Console.ReadKey();
}
}
9.1怎样判定一个类型是否支持一个指定接口

1)使用显式强制转换。

 static void Main(string[] args)
{
//在对象级别调用接口成员
Triangle triangle = new Triangle();
try
{
IPoint point = null;
point =
(IPoint)triangle;
Console.WriteLine(triangle.Points);
Console.ReadKey();
}
catch (InvalidCastException e)
{
Console.WriteLine(e.Message);
}
}

2)as关键字

 IPoint point = null;
point = triangle as IPoint;

3)is关键字

            //在对象级别调用接口成员
Triangle triangle = new Triangle();
try
{ if (triangle is IPoint)
{
Console.WriteLine(triangle.Points);
Console.ReadKey();
}
}
catch (InvalidCastException e)
{
Console.WriteLine(e.Message);
}
9.2接口作为参数
 interface IPoint
{
//接口定义
//1)不指定访问修饰符(默认隐式共有、抽象)
//2)不能实现
string GetNumofName(); //只读属性
//byte Points{ get; } }
//实现接口时要么全要,要么全不要
class Triangle : Object, IPoint
{ //...
public string GetNumofName()
{
return "i am Triangle ";
}
}
class Rect : Object, IPoint
{ //...
public string GetNumofName()
{
return "i am Rect";
}
}
class Program
{
static public string sayname(IPoint p)
{
return p.GetNumofName();
}
static void Main(string[] args)
{
//在对象级别调用接口成员
//Triangle triangle = new Triangle();
//try
//{ // if (triangle is IPoint)
// {
// Console.WriteLine(triangle.Points);
// Console.ReadKey();
// }
//}
//catch (InvalidCastException e)
//{
// Console.WriteLine(e.Message);
//} object[] obj = { new Triangle(), new Rect() };
for (int i = ; i < obj.Length; i++)
{
if (obj[i] is IPoint)
{
IPoint p = (IPoint)obj[i];
Console.WriteLine(sayname(p));
}
}
Console.ReadKey(); }
}

类似的通过as/is关键字的使用,接口也可以作为返回值。

9.3接口数组

接口数组可以包含实现了该接口的任何类或者结构,不论相关不相关。

IPoint[]={new triangle(),new Tree(),new Rect()}

9.4接口的层次结构

1)接口可以继承,继承后如果一个类实现了该接口,则该接口继承的接口成员也需要被实现,同时接口也支持多种继承,若不同接口存在命名冲突,可以通过显式接口解决冲突。

  

C#中的特殊数据类型的更多相关文章

  1. PowerShell中的基础数据类型

    PowerShell是一个面向对象的语言,在申明变量的时候不强制要求申明数据类型,使用$开头来申明变量即可. 基本数据类型 PowerShell本身是基于.Net开发出来的,所以在.Net中的基本数据 ...

  2. MySql中的字符数据类型

    MySql中的varchar类型 1.varchar类型的变化 MySQL数据库的varchar类型在4.1以下的版本中的最大长度限制为255,其数据范围可以是0~255或1~255根据不同版本数据库 ...

  3. [.net 面向对象编程基础] (3) 基础中的基础——数据类型

    [.net 面向对象编程基础] (3) 基础中的基础——数据类型 关于数据类型,这是基础中的基础. 基础..基础..基础.基本功必须要扎实. 首先,从使用电脑开始,再到编程,电脑要存储数据,就要按类型 ...

  4. Mssql中一些常用数据类型的说明和区别

    Mssql中一些常用数据类型的说明和区别 1.bigint 占用8个字节的存储空间,取值范围在-2^63 (-9,223,372,036,854,775,808) 到 2^63-1 (9,223,37 ...

  5. JAVA中分为基本数据类型及引用数据类型

    一.基本数据类型: byte:Java中最小的数据类型,在内存中占8位(bit),即1个字节,取值范围-128~127,默认值0 short:短整型,在内存中占16位,即2个字节,取值范围-32768 ...

  6. SQL Server中的Image数据类型的操作

    原文:SQL Server中的Image数据类型的操作 准备工作,在库Im_Test中建立一张表Im_Info,此表中有两个字段,分别为Pr_Id (INT),Pr_Info (IMAGE),用来存储 ...

  7. 二、java中的基本数据类型

    总结: 1.java中的基本数据类型有byte.short.int.long;float.double;char;boolean. 2.基本数据类型与1相对应分别占1.2.4.8;4.8;2;1.(单 ...

  8. SQL Server 2008空间数据应用系列五:数据表中使用空间数据类型

    原文:SQL Server 2008空间数据应用系列五:数据表中使用空间数据类型 友情提示,您阅读本篇博文的先决条件如下: 1.本文示例基于Microsoft SQL Server 2008 R2调测 ...

  9. Java中的变量数据类型补充

    Java中变量的数据类型的补充 变量按照数据类型进行分类 1.基本数据类型 数值型:①整数类型(byte,short,int,long)②浮点型(float,doubbe)③字符型(char)④布尔型 ...

  10. 如何在Qt中使用自定义数据类型

    这里我们使用下面这个struct来做说明(这里不管是struct还是class都一样): struct Player { int number; QString firstName; QString ...

随机推荐

  1. Mac下常用快捷键(转)

    前提,先熟读键盘快捷键符号:http://www.cnblogs.com/EasonJim/p/6350075.html 基本操作: Command-Z 撤销 Command-X 剪切 Command ...

  2. Docker实战:更轻松、更愉快、更高效

    编者按:借助Docker,我们可以更容易地进行web应用部署,而同时不必头疼于项目依赖.环境变量以及各种配置问题,Docker可以快捷.高效地处理好这一切.而这也是本教程所要实现的主要目的.以下是作者 ...

  3. sublime text 3 快捷键&&使用技巧

    参考文章:https://github.com/jikeytang/sublime-text 这里有很多技巧http://www.jianshu.com/p/3cb5c6f2421c/ 置顶: Ctr ...

  4. MySQL 重命名数据库

    首先创建目标库 create database trgdb; 获取所有源库的表名 use information_schema; select table_name from TABLES where ...

  5. WPF中Style文件引用另一个Style文件中的样式

    第1种方法: 直接在当前Style文件(*.xaml)文件中使用: <ResourceDictionary.MergedDictionaries>来进行合并 <!-- 关键是注意so ...

  6. Unix/Linux文件类型及访问权限

    在Linux系统中,有7种文件类型. 普通文件 (regular file) 目录文件 (directory) 链接文件 (symbolic link) 管道文件 (FIFO) 套接字文件 (sock ...

  7. HDU 6225 Little Boxes

    Little Boxes Little boxes on the hillside.  Little boxes made of ticky-tacky.  Little boxes.  Little ...

  8. 0.ECMAScript 6 简介

    ECMAScript 6简介 ECMAScript 6 简介 ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了.它的目 ...

  9. 十二:video 视频

    属性名 类型 默认值 说明 src String   要播放视频的资源地址 controls Boolean true 是否显示默认播放控件(播放/暂停按钮.播放进度.时间) danmu-list O ...

  10. StatusStrip控件

    态栏用于显示用户状态的简短信息.   StatusStrip控件是由system.windows.forms.statusStrip类提供,作用是在应用程序中标识对话框底部的一栏,通常用于显示应用程序 ...