C#中的特殊数据类型
一、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#中的特殊数据类型的更多相关文章
- PowerShell中的基础数据类型
PowerShell是一个面向对象的语言,在申明变量的时候不强制要求申明数据类型,使用$开头来申明变量即可. 基本数据类型 PowerShell本身是基于.Net开发出来的,所以在.Net中的基本数据 ...
- MySql中的字符数据类型
MySql中的varchar类型 1.varchar类型的变化 MySQL数据库的varchar类型在4.1以下的版本中的最大长度限制为255,其数据范围可以是0~255或1~255根据不同版本数据库 ...
- [.net 面向对象编程基础] (3) 基础中的基础——数据类型
[.net 面向对象编程基础] (3) 基础中的基础——数据类型 关于数据类型,这是基础中的基础. 基础..基础..基础.基本功必须要扎实. 首先,从使用电脑开始,再到编程,电脑要存储数据,就要按类型 ...
- Mssql中一些常用数据类型的说明和区别
Mssql中一些常用数据类型的说明和区别 1.bigint 占用8个字节的存储空间,取值范围在-2^63 (-9,223,372,036,854,775,808) 到 2^63-1 (9,223,37 ...
- JAVA中分为基本数据类型及引用数据类型
一.基本数据类型: byte:Java中最小的数据类型,在内存中占8位(bit),即1个字节,取值范围-128~127,默认值0 short:短整型,在内存中占16位,即2个字节,取值范围-32768 ...
- SQL Server中的Image数据类型的操作
原文:SQL Server中的Image数据类型的操作 准备工作,在库Im_Test中建立一张表Im_Info,此表中有两个字段,分别为Pr_Id (INT),Pr_Info (IMAGE),用来存储 ...
- 二、java中的基本数据类型
总结: 1.java中的基本数据类型有byte.short.int.long;float.double;char;boolean. 2.基本数据类型与1相对应分别占1.2.4.8;4.8;2;1.(单 ...
- SQL Server 2008空间数据应用系列五:数据表中使用空间数据类型
原文:SQL Server 2008空间数据应用系列五:数据表中使用空间数据类型 友情提示,您阅读本篇博文的先决条件如下: 1.本文示例基于Microsoft SQL Server 2008 R2调测 ...
- Java中的变量数据类型补充
Java中变量的数据类型的补充 变量按照数据类型进行分类 1.基本数据类型 数值型:①整数类型(byte,short,int,long)②浮点型(float,doubbe)③字符型(char)④布尔型 ...
- 如何在Qt中使用自定义数据类型
这里我们使用下面这个struct来做说明(这里不管是struct还是class都一样): struct Player { int number; QString firstName; QString ...
随机推荐
- Mac 10.12高级防火墙pfctl教程收集(待实践)
在Mac 10.10之前使用ipfw.之后升级为pfctl.由于Mac自带的GUI防火墙只能针对软件进行放开,且无法针对特定端口入站及出站进行管理.所以使用pfctl能解决这类问题. 收集教程如下: ...
- LINUX 查找替换命令 总结
find /var/ -name "*.php" > /home/tmp 在/var/目录下查找 所有以.php后缀结尾的文件 结果很多,就 > 输出结果到/home ...
- 通过java代码给log4j指定appender
工具代码 import org.apache.log4j.ConsoleAppender; import org.apache.log4j.LogManager; import org.apache. ...
- 解决图片浮动调节不了的问题(使用vertical-align属性)
vertical-align: middle; vertical-align 属性设置元素的垂直对齐方式. baseline 默认.元素放置在父元素的基线上.sub 垂直对齐文本的下标.super ...
- Linq to SharePoint与权限提升(转)
转自http://www.cnblogs.com/kaneboy/archive/2012/01/25/2437086.html SharePoint 2010支持Linq to SharePoint ...
- 【angular5项目积累总结】消息订阅服务
code import { Injectable } from '@angular/core'; import { Subject } from 'rxjs/Subject'; @Injectable ...
- IE浏览器上传文件后返回结果会自动弹出下载框
服务器使用的是node,其它语言的后台没测试过. 在IE低版本浏览器下,当你上传一个文件后后台会返回一些数据,但是IE浏览器会弹出下载提示. 这个问题是之前处理的了,没有细究,今天有人问到这个问题,顺 ...
- WordPress主题开发:主题初始化
在最简单的情况下,一个WordPress主题由两个文件构成: index.php ------------------主模版 style.css -------------------主样式表(注意 ...
- SQL Serever学习9——基础查询语句
SQL语言概述 SQL是结构化查询语言(Structure Query Language),1974年提出,1979年被IBM实现,SQL语言已经成为关系型数据库的标准语言. 包括: DDL数据定义语 ...
- Eclipse常用快捷键之技巧篇
如何让你阅读代码如虎添翼?使用快捷键可以让你快到飞起来~ 显示类的方法和属性:ctrl+o ctrl+o能够看到你的类的层次结构,使你搜索该类某个方法更加的方便 显示类的继承:ctrl+T ctrl+ ...