using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Text;
namespace ConsoleApplication2
{
#region 事件委托
#region 事件
public delegate void mydelegate();
/// <summary>
/// 事件处理方法类
/// </summary>
class MyEventHander
{
public void OnHandler1()
{
Console.WriteLine("调用 OnHandler1() 方法!!");
}
}
/// <summary>
/// 事件声明、触发该事件的方法
/// </summary>
class MyEvent
{
public event mydelegate Event1;
public void FireEvent1()
{
if (Event1 != null)
{
Event1();
}
}
}
class Program
{
static void Main(string[] args)
{
#region 淡定
//int tagID = 6495;
//byte b1,b2;
//b1 = (byte)(tagID >> 8);
//b2 = (byte)tagID;
//System.Console.WriteLine("b1:{0:X2},b2:{1:X2}", b1, b2);
#endregion
MyEvent b = new MyEvent();//实例化对象,b为 事件类 对象名
MyEventHander a = new MyEventHander();//实例化对象,a为 事件处理方法类 对象名
b.Event1 += new mydelegate(a.OnHandler1);//将事件处理方法绑定到事件
b.FireEvent1();//事件触发方法
}
}
#endregion
#region 事件
public delegate void mydelegate(int c, int n);//声明一个事件委托
/// <summary>
/// 事件声明、事件触发方法类
/// </summary>
public class Shape
{
protected int color = 0;
public event mydelegate ColorChange;//声明一个事件
public int pcolor//定义属性
{
set
{
int ocolor = color;
color = value;
ColorChange(ocolor, color);
}
get { return color; }
}
//public Shape()//构造函数
//{
// color = 0;
//}
}
/// <summary>
/// 事件处理方法类
/// </summary>
public class MyEventHander
{
public void EentHander(int c, int n)
{
Console.WriteLine("事件处理方法!");
}
}
class Program
{
static void Main(string[] args)
{
Shape obj = new Shape();
MyEventHander obj1 = new MyEventHander();
obj.ColorChange += new mydelegate(obj1.EentHander);
}
}
#endregion
#region 委托
delegate void mydelegate(int n);
class MyDeClass
{
public void fun1(int n)
{
Console.WriteLine("{0}的2倍={1}", n, 2 * n);
}
public void fun2(int n)
{
Console.WriteLine("{0}的3倍={1}", n, 3 * n);
}
}
class Program
{
static void Main(string[] args)
{
MyDeClass obj = new MyDeClass();
mydelegate p = new mydelegate(obj.fun1);
p(100);
p = new mydelegate(obj.fun2);
p(2);
}
}
#endregion
#region 委托
delegate double mydelegate(double x, double y);
class MyDeClass
{
public double add(double x, double y)
{
return x + y;
}
public double sub(double x, double y)
{
return x - y;
}
public double mul(double x, double y)
{
return x * y;
}
public double div(double x, double y)
{
return x / y;
}
}
class Program
{
static void Main(string[] args)
{
MyDeClass obj = new MyDeClass();
mydelegate p = obj.add;
Console.WriteLine("5+8={0}", p(5, 8));
p = obj.sub;
Console.WriteLine("5-8={0}", p(5, 8));
p = obj.mul;
Console.WriteLine("5*8={0}", p(5, 8));
p = obj.div;
Console.WriteLine("5/8={0}", p(5, 8));
}
}
#endregion
#region 委托
delegate void mydelegate(double x, double y);
class MyDeClass
{
public void add(double x, double y)
{
Console.WriteLine("{0}+{1}={2}", x, y, x + y);
}
public void sub(double x, double y)
{
Console.WriteLine("{0}-{1}={2}", x, y, x - y);
}
public void mul(double x, double y)
{
Console.WriteLine("{0}*{1}={2}", x, y, x * y);
}
public void div(double x, double y)
{
Console.WriteLine("{0}/{1}={2}", x, y, x / y);
}
}
class Program
{
static void Main(string[] args)
{
MyDeClass obj = new MyDeClass();
//mydelegate p, a;
//a = obj.add;
//p = a;
//a = obj.sub;
//p += a;
//a = obj.mul;
//p += a;
//a = obj.div;
//p += a;
//p(5, 8);
mydelegate p = new mydelegate(obj.add);
p += obj.div;
p += obj.mul;
p += obj.sub;
p(5, 10);
}
}
#endregion
#region 使委托与匿名方法关联
delegate void mydelegate(string mystr);//====没有方法名称的方法,当将委托与匿名方法关联时,直接给出方法的函数体====//
class Program
{
static void Main(string[] args)
{
//委托类型名 对象名 返回类型 (参数列表) 匿名方法代码
mydelegate p = delegate(string mystr){Console.WriteLine(mystr);};
p("valeb");
}
}
#endregion
#endregion
#region 泛型
#region 一元运算符重载
class MyOp
{
private int n;
public MyOp(int n1)
{
n = n1;
}
public static MyOp operator ++(MyOp obj)
{
return new MyOp(obj.n + 1);
}
public void dispdata()
{
Console.WriteLine("n={0}", n);
}
}
class Program
{
static void Main(string[] args)
{
MyOp a = new MyOp(2);
a++;
a.dispdata();
}
}
#endregion
#region List<T>
struct Stud
{
public int sno;
public string name;
}
class Program
{
static void Main(string[] args)
{
int i;
List<Stud> myset = new List<Stud>();
Stud s1 = new Stud();
s1.sno = 101; s1.name = "valeb";
myset.Add(s1);
Stud s2 = new Stud();
s2.sno = 102; s2.name = "蒲飞龙";
myset.Add(s2);
Stud s3 = new Stud();
s3.sno = 103; s3.name = "岳坪";
myset.Add(s3);
Console.WriteLine("元素序列");
Console.WriteLine("下标 学号 姓名");
i = 0;
foreach (Stud st in myset)
{
Console.WriteLine("{0} {1} {2}", i, st.sno, st.name);
i++;
}
Console.WriteLine("容量:{0}", myset.Capacity);
Console.WriteLine("元素个数:{0}", myset.Count);
Console.WriteLine("在索引2处插入一个元素");
Stud s5 = new Stud();
s5.sno = 105; s5.name = "宏观";
myset.Insert(2, s5);
Console.WriteLine("元素序列");
Console.WriteLine("下标 学号 姓名");
i = 0;
foreach (Stud st in myset)
{
Console.WriteLine("{0} {1} {2}", i, st.sno, st.name);
i++;
}
}
}
#endregion
#endregion
#region 继承
#region 继承
class MyClassa
{
private int n = 9;
protected int m;
public void afun()
{
Console.WriteLine("I'm Is A {0}", n);
}
}
class MyClassb : MyClassa
{
public int x=10;
public void bfun()
{
}
}
class Program
{
static void Main(string[] args)
{
MyClassb b = new MyClassb();
b.afun();
Console.WriteLine("{0}", b.x);
}
}
#endregion
#region 继承(调用默认构造函数的次序)
class A
{
public A()
{
Console.WriteLine("A-a");
}
public int a = 10;
}
class B:A
{
public B()
{
Console.WriteLine("B-b");
}
public int b = 9;
}
class C:B
{
public C()
{
Console.WriteLine("C-c");
}
public int c = 8;
}
class Program
{
static void Main(string[] args)
{
C c = new C();
int aa = c.a;
int bb = c.b;
int cc = c.c;
Console.WriteLine("{0},{1},{2}",aa,bb,cc);
}
}
#endregion
#region 继承(调用默认构造函数的次序)销毁对象时
class A
{
~A()//析构函数:在对象不再需要时,希望确保函数所占的存储空间能被收回。所以其为:专门用于释放被占用的系统资源。
{
Console.WriteLine("A");
}
}
class B:A
{
~B()//析构函数的性质:一个类只能有一个析构函数;其没有参数;不能重载;没有返回值;不能被继承。
{
Console.WriteLine("B");
}
}
class C:B
{
~C()
{
Console.WriteLine("C");
}
}
class Program
{
static void Main(string[] args)
{
C c = new C();
}
}
#endregion
#region 继承(调用重载构造函数的次序)
class A
{
private int x;
public A()
{
Console.WriteLine("调用类A构造函数");
}
public A(int x1)
{
x = x1;
Console.WriteLine("调用类A重载构造函数");
}
~A()
{
Console.WriteLine("A:x={0}", x);
}
}
class B : A
{
private int y;
public B(int x1)
{
Console.WriteLine("调用类B构造函数");
}
public B()
{
}
public B(int x1, int y1)
: base(x1)
{
y = y1;
Console.WriteLine("调用类B重载构造函数");
}
~B()
{
Console.WriteLine("B:y={0}", y);
}
}
class C : B
{
private int z;
//public C()
//{
// Console.WriteLine("调用类C构造函数");
//}
public C(int x1)
: base(x1)
{
}
public C(int x1, int y1, int z1)
: base(x1, y1)
{
z = z1;
Console.WriteLine("调用类C重载构造函数");
}
~C()
{
Console.WriteLine("C:z={0}", z);
}
}
class Prcgram
{
static void Main(string[] agrs)
{
C c = new C(1, 2, 3);
}
}
#endregion
#region 禁止类继承
sealed class A
{
public A()
{
Console.WriteLine("A");
}
}
class B:A //这里继承不了,因为A类有 sealed 修饰符,其作用是禁止继承
{
public B()
{
Console.WriteLine("B");
}
}
class C:B
{
public C()
{
Console.WriteLine("C");
}
}
class Program
{
static void Main(string[] agrs)
{
C c = new C();
}
}
#endregion
#endregion
#region 重写
//定义一个F类
class F
{
//定义一个公有Method方法,子类中用new隐藏了本方法
public void Method()
{
Console.WriteLine("我是父类中的Method方法");
Console.WriteLine();
}
//定义了一个虚方法Method1,子类中重写了Method1.
public virtual void Method1()
{
Console.WriteLine("我是父类中的Method1方法");
Console.WriteLine();
}
//定义了一个虚方法Method2,子类中重写了Method2.子类中使用了base.method1,再次调用被重写了的Method1
public virtual void Method2()
{
Console.WriteLine("我是父类中的Method2方法");
Console.WriteLine();
}
}
//定义一个继承F类的S类
class S : F
{
//定义一个公有Method方法,隐藏了父类的方法
public new void Method()
{
Console.WriteLine("我是子类中的Method方法,使用new关键字,显式的隐藏父类中的同名方法");
Console.WriteLine();
}
//定义一个重写父类Method1的方法Method1。
public override void Method1()
{
Console.WriteLine("我是子类中的Method1方法,覆盖父类中的同名方法,此时S中没有了父类中Method1方法");
Console.WriteLine();
}
//定义一个重写父类Method1的方法Method1,同时使用base调用父类的Method1。
public override void Method2()
{
Console.WriteLine("我是子类中的Method2,覆盖父类中的同名方法,调用base.method1");
base.Method1();
Console.WriteLine();
}
}
class Program
{
static void Main(string[] args)
{
// 创建一个S类的s对象
S s = new S();
// 创建一个F类的f对象
F f = new F();
//创建一个F类的fs对象,但是用S类来实现,这种方式是允许的。
//意思就是父亲到了儿子的房子去了,看到的油画应该是父亲的油画,房子还是从父亲那继承下的房子。
//对象fs所引用出的成员,实际是从父类中继承来的成员,不是继承来的成员(如儿子自己买的电器)fs是无权访问的。
//父类需要子类去实现的这种方式会在抽象类和接口中会用到。
F fs = new S();
//先观察一下子类使用new的Method方法中三对象的结果。
//-------------------------------------------
//子类的对象s引用的Method方法打印出的是子类的Method方法
s.Method();
//子类中的Method方法,因为使用了new,只是覆盖了父类的Method方法,
//所以父类的对象fs引用的Method方法打印出的是还是从父类中继承下来的Method方法
fs.Method();
//父类中的Method方法不变
f.Method();
Console.WriteLine("---------");
//先观察一下子类使用override的Method1方法中三对象的结果。
//-------------------------------------------
//子类的对象s引用的Method1方法打印出的是子类的Method1方法
s.Method1();
//子类中的Method1方法,因为使用了override,重写了父类的Method1方法,
//所以父类的对象fs引用的Method1方法打印出的是还是从子类中继承下来的Method1方法
//子类中只存在子类的Method1方法,结果如上.
fs.Method1();
//父类中的Method方法不变
f.Method1();
Console.WriteLine("---------");
//先观察一下子类使用override和base.method1的Method2方法中三对象的结果。
//-------------------------------------------
//因为使用了override,重写了父类的Method2方法,
//因为使用了base.Method1,所以在子类中会调用父类的Method1方法
//子类的对象s引用的Method1方法打印出的是子类的Method2方法和父类的Method1方法
s.Method2();
//子类中的Method2方法,因为使用了override,重写了父类的Method2方法,
//所以父类的对象fs引用的Method2方法打印出的是还是从子类中继承下来的Method2方法
//子类中只存在子类的Method2方法,结果如上.
fs.Method2();
//父类中的Method方法不变
f.Method2();
Console.WriteLine("---------");
}
}
#endregion
#region 多态性
#region 派生方法替换基方法
<summary>
使用new 让派生方法替换基方法
</summary>
class A
{
public void fun()
{
Console.WriteLine("A");
}
}
class B : A
{
new public void fun()
{
Console.WriteLine("B");
}
}
class Program
{
static void Main(string[] agrs)
{
B b = new B();
b.fun();
}
}
#endregion
==============重写与重载====================//
/*重写:是指在子类中编写有相同名称和参数的方法 === virtual 关键字,不能与 static abstract override 一起用 */
/*重载:是指在编写(在同一个类中)具有相同的名称,却有不同的参数方法*/
#region 重写方法
/* override 方法提供从基类继承的成员的新实现,通过override声明重写的方法称为重写基方法,重写的基方法必须与override方法具有相同的签名*/
/*不能重写非虚方法或静态方法。重写的基方法必须是virtual abstract 或override的*/
/*override声明不能更改virtual方法的可访问性*/
/*不能使用修饰符new static virtual abstract 来修改override方法 */
/*重写属性声明必须指定与继承属性完全相同的访问修饰符、类型和名称,并且被重写的属性必须是virtual abstract或override的 */
#endregion
#region 重写方法例子
class Student
{
protected int no;
protected string name;
protected string tname;
public void setdata(int no1, string name1, string tname1)
{
no = no1;
name = name1;
tname = tname1;
}
public virtual void dispdata()//虚方法
{
Console.WriteLine("本科生 学号:{0},姓名:{1},班主任:{2}",no,name,tname);
}
}
class Graduate:Student
{
public override void dispdata()//重写方法
{
Console.WriteLine("研究生 学号:{0},姓名:{1},班主任:{2}", no, name, tname);
}
}
class Program
{
static void Main(string[] agrs)
{
Student s = new Student();
s.setdata(101, "张三", "张一");
s.dispdata();
Graduate g = new Graduate();
g.setdata(102, "李四", "李二");
g.dispdata();
}
}
/*Student类是基类,派生出Graduate类,在Graduate类中重写dispdata方法,所以在基类中要将其修饰符指定为virtual, */
/*在执行g.dispdata()语句时,是调用Graduate类中的dispdata方法而不是基类的dispdata方法。*/
#endregion
#region 调用基类构造函数(base的用法)
public class Rectangle //长方形类
{
public const double PI = Math.PI;
protected double x, y;
public Rectangle()//基数构造函数(无参)
{
//无参构造函数体(这里没有用到这种构造函数,所以没有函数体)
}
public Rectangle(double x1, double x2)//基类构造函数(带参)
{
x = x1; y = x2;
}
public virtual double Area()//求面积方法(虚方法)
{
return x * y;
}
}
public class Circle : Rectangle//圆类
{
public Circle(double r)
: base(r, 0) { }//调用基类构造函数(带参)
/*=========本应该这样写,因为继承,所有就有所变================
double xx;
public Circle(double r)
{
xx = r;
}
==========================================================*/
/*===============================================================================
:base(r,0)的意思先看下面
public Circle(double r) (可以说成)等于 public Rectangle(double x1, double x2)
但是后者是两个参,所以 :base(r,0)的第二个参会用0
================================================================================*/
public override double Area()//求面积方法重写
{
return PI * x * x;
}
}
class Sphere : Rectangle//圆球体类
{
public Sphere(double r)
: base(r, 0) { }
public override double Area()//求面积方法重写
{
return 4 * PI * x * x;
}
}
public class Cylinder : Rectangle //圆柱体类
{
public Cylinder(double r, double h)
: base(r, h) { }
public override double Area()//求面积方法重写
{
return 2 * PI * x * x + 2 * PI * x * y;
}
}
public class Program
{
static void Main(string[] args)
{
double x = 2.4, y = 5.6;
double r = 3.0, h = 5.0;
Rectangle t = new Rectangle(x, y);
Circle c = new Circle(r);
Rectangle s = new Sphere(r);
Rectangle l = new Cylinder(r, h);
Console.WriteLine("长{0},宽{1}的面积为:{2:F2}", x, y, t.Area());
Console.WriteLine("半径为{0}的圆球面积:{1:F2}", r, c.Area());
Console.WriteLine("半径为{0}的圆球体表面积:{1:F2}", r, s.Area());
Console.WriteLine("半径为{0},高为{1}的圆柱体表面积:{2:F2}", r, h, l.Area());
}
}
#endregion
#region 从派生类中访问基类的成员
public class Person
{
protected string ssn = "444-55-6666";
protected string name = "John L. Malgraine";
public virtual void GetInfo()
{
Console.WriteLine("Name: {0}", name);
Console.WriteLine("SSN: {0}", ssn);
}
}
class Employee : Person
{
public string id = "ABC567EFG";
public override void GetInfo()
{
// Calling the base class GetInfo method:
base.GetInfo();
Console.WriteLine("Employee ID: {0}", id);
}
}
class TestClass
{
static void Main()
{
Employee E = new Employee();
E.GetInfo();
}
}
#endregion
#region 调用基类上已被其他方法重写的方法
public class Person
{
protected string ssn = "444-55-6666";
protected string name = "John L. Malgraine";
public virtual void GetInfo()
{
Console.WriteLine("Name: {0}", name);
Console.WriteLine("SSN: {0}", ssn);
}
public virtual void GetInfo1()
{
Console.WriteLine("Name: {0}-1", name);
Console.WriteLine("SSN: {0}-1", ssn);
}
}
class Employee : Person
{
public string id = "ABC567EFG";
public override void GetInfo()
{
// Calling the base class GetInfo method:
base.GetInfo1(); //GetInfo1并没有被重写
Console.WriteLine("Employee ID: {0}", id);
}
}
class Program
{
static void Main(string[] args)
{
Employee E = new Employee();
E.GetInfo();
}
}
#endregion
#region 指定创建派生类实例时应调用的基类构造函数
public class BaseClass
{
int num;
public BaseClass()
{
Console.WriteLine("in BaseClass()");
}
public BaseClass(int i)
{
num = i;
Console.WriteLine("in BaseClass(int i)");
}
public int GetNum()
{
return num;
}
}
public class DerivedClass : BaseClass
{
// This constructor will call BaseClass.BaseClass()
public DerivedClass()
: base()
{
}
// This constructor will call BaseClass.BaseClass(int i)
public DerivedClass(int i)
: base(i)
{
}
static void Main()
{
DerivedClass md = new DerivedClass();
DerivedClass md1 = new DerivedClass(1);
}
}
#endregion
#endregion
#region 抽象类
/*在 类的声明 中使用abstract修饰符的类称为 抽象类*/
/*========================抽象类的特点:==================
* 抽象类不能实例化&
* 抽象类可以包含抽象方法和抽象访问器&
* 抽象类可以存在非抽象的方法&不能用sealed修饰符修改抽象类(抽象类不能被继承)&
* 从抽象类派生 的非抽象类必须包括继承的所有抽象方法和抽象访问器的实现&
* 抽象类可以被抽象类所继承,结果仍是抽象类*/
/*==========================================================================*/
/*==========================抽象方法=============================
* 声明一个抽象方法使用abstract关键字。
* 抽象方法是隐式的虚方法。
* 只允许在抽象类中使用抽象方法声明
* 一个类中可以包含一个或多个抽象方法
* 因为抽象方法声明不提供实际的实现,所以没有方法体;方法声明只是以一个分号结束,并且在签名后没有大括号{}。如:abstract public int fun();
* 非抽象方法却是这样的:
public int fun()
{
方法主体
}
* 抽象方法实现由一个重写方法提供,此重写方法是非抽象类的成员
* 实现抽象类用“:” 实现抽象方法用 oveeride 关键字
* 在抽象方法声明中使用 static 或 virtual 修饰符是错误的
* 抽象方法被实现后,不能更改修饰符 */
abstract class A //抽象类声明
{
abstract public int fun();//抽象方法声明
}
class B : A //实现抽象类用“:”
{
int x, y;
public B(int x1, int y1)
{
x = x1;
y = y1;
}
public override int fun()//实现抽象方法用 oveeride 关键字
{
return x * y;
}
}
class Program
{
static void Main(string[] args)
{
B b = new B(2, 3);
Console.WriteLine("{0}", b.fun());
}
}
/*==========================抽象属性=================================*/
/*抽象属性具有的特性
* 在静态属性上使用abstract 修饰符是错误的
* 在派生类中,通过包括使用override修饰符的属性声明,可以重写抽象的继承属性
* 抽象属性声明不提供属性访问器的实现,它只声明该类支持属性,而将访问器实现留给其派生类
*/
abstract class A
{
protected int x = 2;
protected int y = 3;
public abstract void fun();//抽象方法
public abstract int px { get; set; }//抽象属性px
public abstract int py { get; }//抽象属性py
}
class B : A
{
public override void fun()
{
x++; y++;
}//抽象方法实现
public override int px
{
set
{ x = value; }
get
{ return x + 10; }
}//抽象属性实现
public override int py
{
get
{
return y + 10;
}
}//抽象属性实现
}
class Program
{
static void Main(string[] args)
{
B b = new B();
b.px = 5;
b.fun();
Console.WriteLine("x={0},y={1}",b.px,b.py);
}
}
#endregion
#region 接口
/*/==========接口==========/*/
/*------什么是接口------*/
/* 接口是类之间交互内容的一个抽象,
* 把类之间需要交互的内容抽象出来定义成接口,
* 可以更好的控制类之间的逻辑交互。
*/
/*--------接口特性--------*/
/* 接口类似于抽象基类。继承接口的任何非抽象类型都必须实现接口的所有成员。
* 不能直接实例化接口。
* 接口可以包含事件、索引器、方法和属性(不包含字段)
* 接口不包含方法的实现
* 类和结构可从多个接口继承
* 接口自身可从多个接口继承
*/
#endregion
#region 接口的定义
/*==========接口的定义===========*/
/*>>>>> 声明接口 <<<<<*/
/* 语法格式:
[接口修饰符] interface 接口名[:父接口列表]
{
接口成员定义
}
*/
接口修饰符可以是:new、public、protected、 internal、 private
new 修饰符是在嵌套接口中唯一被允许存在的修饰符,表示用相同的名称隐藏一个继承的成员。
/*==================接口的继承===================*/
/* 接口可以从0或N个接口中继承。当一个接口从多个接口中继承时,用“:”后跟被继承的接口名称,这多个接口之间用“,”号分隔。
* 被继承的接口应该是可以被访问的,即不能从internal或internal类型的接口继承
*/
对一个接口的继承也就继承了接口的所有成员。
/*例如:先声明了接口 IA 和 IB ,另一接口 IC 是从它们派生的。
public interface IA //接口声明
{
void mymetthod1();
}
public interface IB //接口声明
{
int mymethod2(int x);
}
public interface IC : IA, IB //接口IC从IA和IB继承
{
}
==继承后 IC 包含了从 IA、IB 中继承来的 mymetthod1、mymethod2 二个方法
*/
/*===============*/
#endregion
#region 接口的成员
/*接口可以声明0个或N个成员。一个接口的成员不止包括自身声明的成员,还包括从父接口继承的成员。
所有接口成员默认都是公有的,接口成员声明中包含任何修饰符都是错误的。*/
------接口方法成员-----//
/* 语法格式: 返回类型 方法名([参数表]) */
#endregion
#region 接口属性成员
-------接口属性成员---------//
语法格式: 返回类型 属性名 {get;或 set;}
/* 例如:声明一个接口 IA ,其中接口属性 x 为只读,y 可读可写,z为只写 */
/*
public interface IA
{
int x { get; }
int y { get; set; }
int z { set; }
}
*/
#endregion
#region 接口索引器成员
/*----------接口索引器成员---------*/
语法格式: 数据类型 this[索引参数表] {get; 或 set;}
/*
public interface Ia
{
string this[int index]
{
get;
set;
}
}
*/
#endregion
#region 接口事件成员
语法格式: event 代表名 事件名
如:以下声明一个接口 IA ,其中包含一个接口事件成员
/*
public delegate void mydelegate();//声明委托
public interface IA
{
event mydelegate myevent;
}
*/
#endregion
#region 接口的实现
/* 接口的实现分为:隐式、显式实现。如果类或者结构要实现的是单个接口,可以使用隐式实现;
如果类或者结构继承了多个接口,那么接口中相同名称成员就要显式实现。
显式实现是通过使用接口的完全限定名来实现接口成员的。*/
/* 语法格式:
class 类名:接口名列表
{
类实体
}
*/
当一个类实现一个接口时,这个类就必须实现整个接口,而不能选择实现接口的某一部分
一个接口可以由多个类来实现,而在一个类中也可以实现 一个或多个接口
一个类可以继承一个基类,并同时实现一个或多个接口
#endregion
#region 隐式实现接口成员
如果类实现了某个接口,它必然隐式地继承了该接口成员,只不过增加了该接口成员的具体实现。
若要隐式实现接口成员,类中的对应成员必须是公共的、非静态的,
并且与接口成员具有相同的名称和签名。
/*
interface Ia //声明接口
{
float getarea();//接口成员声明
}
public class rectangle :Ia //rectangle继承接口 Ia
{
float x, y;
public rectangle(float x1, float y1) //构造函数
{
x = x1; y = y1;
}
public float getarea() //隐式接口实现,必须使用 public
{
return x * y;
}
}
class Program
{
static void Main(string[] args)
{
rectangle box1 = new rectangle(2.5f, 3.0f); //定义一个类实例
Console.WriteLine("长方形面积:{0}",box1.getarea());
}
}
*/
***一个接口可以被多个类继承,在这些类中实现该接口的成员,这样接口就起到提供统一界面的作用。//***///
/*
interface Ia //声明接口
{
int fun(); //接口成员
}
class A:Ia //类 A 继承接口 Ia
{
int x, y;
public A(int a, int b) //构造函数
{
x = a; y = b;
}
public int fun() //隐式接口成员实现
{
return x - y;
}
}
class B:Ia //类 B 继承接口 Ia
{
int x, y;
public B(int a, int b) //构造函数
{
x = a; y = b;
}
public int fun() //隐式接口成员实现
{
return x + y;
}
}
class Program
{
static void Main(string[] args)
{
A a = new A(5, 2);
Console.WriteLine("{0}",a.fun());
B b = new B(5, 2);
Console.WriteLine("{0}",b.fun());
}
}
* */
#endregion
#region 显式实现接口成员
当类实现接口时,如给出了接口成员的完整名称 即带有接口名前缀,
则称这样实现的成员为显式接口成员,
其实现被称为显式接口实现 。
显式接口成员实现不能使用任何修饰符
interface Ia //声明接口
{
float getarea(); //接口成员声明
}
public class Rectangle:Ia //类 Rectangle 继承接口 Ia
{
float x, y;
public Rectangle(float a, float b) //构造函数
{
x = a; y = b;
}
float Ia.getarea() //显式接口成员实现,带有接口名前缀,不能使用 public 。这里通过 Ia.getarea()来调用接口成员。
{
return x * y;
}
}
public class myclass:Ia
{
float x1, y1;
public myclass(float a1, float b1)
{
x1 = a1;
y1 = b1;
}
float Ia.getarea() //当接口成员由类显式实现时,只能通过使用对接口的引用来访问该成员。这里通过 Ia.getarea()来调用接口成员。
{
return x1 + y1;
}
}
class Program
{
static void Main(string[] args)
{
Rectangle box1 = new Rectangle(2.5f, 3.0f);//定义一个类实例
Ia ia1 = (Ia)box1; //定义一个接口实例 --- 等同于 Ia ia = mc;
Console.WriteLine("长方形面积:{0}", ia1.getarea());
//Console.WriteLine("长方形面积:{0}", box1.getarea());//错误:因为显式实现时导致隐藏接口成员。如果成员只应通过接口调用,才考虑显式实现接口成员
myclass mc = new myclass(2.5f, 5.5f);
Ia ia = mc; //定义一个接口实例
Console.WriteLine("长方形面积:{0}",ia.getarea());
}
}
#endregion
#region 接口映射
接口通过类实现,对于接口中声明的每一个成员都应该对应着类的一个成员,这种对应关系是由接口映射来实现的。
类的成员A 及其所映射的接口成员B 之间必须满足以下条件。
/*
* 如果A和B都是成员方法,那么A和B的名称、返回类型、形参个数和每个形参的类型都应该是一致的。
* 如果A和B都是成员属性,那么A和B的名称和类型都应该是一致的。
* 如果A和B都是事件,那么A和B的名称和类型都应该是一致的。
* 如果A和B都是索引器,那么A和B的名称、形参个数和每个形参的类型都应该是一致的。
*/
一个接口成员映射哪一个类的成员?
假设:类C实现接口IA 的一个接口fun,此时fun的映射过程如下:
/*
* 如果类C中存在一个显式接口成员实现,它与IA的接口成员的fun相应,则由它来实现fun成员。
* 如果类中找不到匹配的显式接口成员实现,则看类C中是否存在一个与fun 相匹配的非静态的公有成员,若有,则被认为是IA的接口成员的fun的实现。
* 如果以上都不满足,则在类C的基类中一个基类D,用D来代替C进行重复寻找,直到找到一个满足条件的类成员实现。如果都没有找到,则报告一个错误。
* */
interface Ia
{
double fun1();
int fun2();
}
class A
{
public int fun2()
{
return 2;
}
}
class B:A,Ia
{
double x;
public B(double y)
{
x = y;
}
public double fun1()
{
return x;
}
}
class Program
{
static void Main(string[] args)
{
B b = new B(2.5);
Console.WriteLine("{0}",b.fun1());
Console.WriteLine("{0}",b.fun2());
}
}
#endregion
#region 接口实现的继承
interface Ia //接口声明
{
int fun(); //接口成员声明
}
class A : Ia //实现接口 Ia
{
public int fun() //接口成员实现
{
return 1;
}
}
class B : A //从类A 派生类B
{
new public int fun() //隐藏基类A中的fun方法
{
return 2;
}
}
class Program
{
static void Main(string[] args)
{
A a = new A();
Console.WriteLine("{0}", a.fun());//调用A.fun
B b = new B();
Console.WriteLine("{0}", b.fun());//调用B.fun
Ia ia = a;//定义一个接口实例
Console.WriteLine("{0}", ia.fun());//调用A.fun
Ia ib = b;//定义一个接口实例
Console.WriteLine("{0}", ib.fun());//调用A.fun
}
}
#endregion
#region 重新实现接口
所谓接口的重新实现是指:某个类可以通过它的基类中包含已被基类实现的接口再一次的实现该接口。
当重新实现接口时,不管派生类建立的接口映射如何,它从事基类继承的接口映射并不会受到影响。
interface Ia
{
void fun();
}
class A:Ia
{
void Ia.fun()
{
//...
}
}
class B:A,Ia
{
public void fun()
{
//.....
}
}
其中类A 把 Ia.fun 映射到了 A.Ia.fun 上,但是这并不影响在 B 中的重实现。在 B 中的重实现中,Ia.fun 被映射到 B.fun 之上
在接口的重实现时,继承而来的公有成员定义和继承而来的显式接口成员的定义都参与到了接口映射的过程。
interface Ia //接口声明
{
int fun1();//接口成员声明
int fun2();//接口成员声明
int fun3();//接口成员声明
}
class A:Ia //从接口 Ia 继承
{
int Ia.fun1() //显式接口实现
{
return 1;
}
int Ia.fun2() //显式接口实现
{
return 2;
}
int Ia.fun3() //显式接口实现
{
return 3;
}
}
class B:A,Ia //从 A 类和接口 Ia 继承
{
public int fun1() // 隐式接口实现
{
return 11;
}
int Ia.fun2() //显式接口实现
{
return 22;
}
}
class Program
{
static void Main(string[] args)
{
A a = new A();
B b = new B();
Ia ia = a;
Console.WriteLine("{0}", ia.fun1());//调用A.fun1()
Console.WriteLine("{0}", ia.fun2());//调用A.fun2()
Console.WriteLine("{0}", ia.fun3());//调用A.fun3()
Ia ib = b;
Console.WriteLine("{0}", ib.fun1());//调用B.fun1()
Console.WriteLine("{0}", ib.fun2());//调用B.fun2()
Console.WriteLine("{0}", ib.fun3());//调用A.fun3()
}
}
接口 Ia 在 B中的实现 把接口方法 映射到了 B.fun1()、Ia.B.fun2() 和 Ia.A.fun3()。
也就是说,类在 实现 一个接口时,同时隐式地实现了该接口的所有父接口。
同样,类在 重实现 一个接口的同时,隐式地重实现了该接口的所有父接口。
#endregion
#region 接口在集合排序中的应用
#region ArrayList 类的排序方法
ArrayList类对象不仅可以存放数值、字符串,还可以存放其他类的对象和结构变量。
/*
其提供的排序方法如下:
* ArrayList.Sort(IComparable):使用每个元素的IComparable接口实现对整个ArrayList类中的元素进行排序。
* ArrayList.Sort(IComparer):使用指定的比较器对整个ArrayList中的元素进行排序。
* ArrayList.Sort(Int32,Int32,IComparer):使用指定的比较器对ArrayList中某个范围内的元素进行排序。*/
#endregion
#region IComparable 接口
IComparable 接口定义通用的比较方法,由值类型或类实现以创建类型特定的比较方法。
其公共成员有CompareTo,它用于比较当前实例与同一类型的另一对象。语法如下:
int CompareTo(object obj)
其中,obj表示与此实例进行比较的对象。其返回值是一个32位有符号整数,指示要比较的对象的相对顺序。返回值的含义如下:
<0 :此实例小于obj
=0 : 此实例等于obj
>0 : 此实例大于obj
IComparable接口的CompareTo方法提供默认排序次序,如果需要改变其排序方式,可以在相关类中实现CompareTo方法,以订制其比较功能。
class Program
{
class Stud : IComparable//从接口派生
{
int xh; //学号
public int pxh //pxh属性
{
get { return xh; }
}
string xm; //姓名
public string pxm //pxm属性
{
get { return xm; }
}
int fs; //分数
public int pfs //pfs属性
{
get { return fs; }
}
public Stud(int no, string name, int dagree)
{
xh = no; xm = name; fs = dagree;
}
public void disp()//输出学生信息
{
Console.WriteLine("\t{0}\t{1}\t{2}", xh, xm, fs);
}
public int CompareTo(object obj) //实现接口方法
{
Stud s = (Stud)obj; //转换为Stud实例
if (pfs < s.pfs) return 1;
else if (pfs == s.pfs) return 0;
else return -1;
}
}
static void disparr(ArrayList myarr, string str)//输出所有学生信息
{
Console.WriteLine(str);
Console.WriteLine("\t学号\t姓名\t分数");
foreach (Stud s in myarr)
{
s.disp();
}
}
static void Main(string[] args)
{
int i, n = 4;
ArrayList myarr = new ArrayList();
Stud[] st = new Stud[4] { new Stud(1,"Smith",82),
new Stud(4,"valeb",99),
new Stud(3,"john",78),
new Stud(2,"mary",88)};
for (i = 0; i < n; i++)//将对象添加到myarr集合中
{
myarr.Add(st[i]);
}
disparr(myarr, "排序前:");
myarr.Sort();
disparr(myarr, "按分数降序排序后:");
}
//上述程序中声明了一个学生类Stud,包含学号、姓名、分数字段,并设计了对应的属性和相关方法。
//由于要对若干学生按照分数降序,需改变默认的排序方式,所以Stud类从IComparable接口派生并实际CompareTo方法。
//在主函数中定义了一个集合对象myarr,将st对象数组中所有对象添加到myarr中。调用ArrayList类的Sort()方法,
//在排序比较时自动使用Stud类中实现的CompareTo方法。
}
#endregion
#region IComparer 接口
IComparer 接口定义两个对象的通用比较方法。
其公共成员有Compare.Compare方法比较两个对象并返回一个值,
指示一个对象是小于、等于还是大于另一个对象。其语法如下:
int Compare(object x,object y)
其中,X 表示要比较的第一个对象,Y 表示要比较的第二个对象。其返回值是一个32位有符号整数
指示要比较的对象的相对顺序。返回值的含义如下:
小于0:X 小于 Y
等于0:x 等于 y
大于0:x 大于 y
通常声明一个类(从IComparer接口派生),其中实现Compare方法,以订制其比较功能,
然后再调用排序方法以该类的对象作为参数,这样在排序时会自动使用该订制的Compare方法。
class Program
{
class Stud
{
int xh; string xm; int fs;
public int pxh
{
get { return xh; }
}
public string pxm
{
get { return xm; }
}
public int pfs
{
get { return fs; }
}
public Stud(int no, string name, int degree)
{
xh = no; xm = name; fs = degree;
}
public void disp()
{
Console.WriteLine("\t{0}\t{1}\t{2}", xh, xm, fs);
}
}
public class myCompareClassxh : IComparer
{
int IComparer.Compare(object x, object y)
{
Stud a = (Stud)x;
Stud b = (Stud)y;
if (a.pxh > b.pxh)
{
return 1;//x 大于 y
}
else if (a.pxh == b.pxh)
{
return 0;
}
else
{
return -1;
}
}
}
public class myCompareClassxm : IComparer
{
int IComparer.Compare(object x, object y)
{
Stud a = (Stud)x;
Stud b = (Stud)y;
return string.Compare(a.pxm, b.pxm);
}
}
public class myComparerfs : IComparer
{
int IComparer.Compare(object x, object y)
{
Stud a = (Stud)x;
Stud b = (Stud)y;
if (a.pfs < b.pfs)
{
return 1;
}
else if (a.pfs == b.pfs)
{
return 0;
}
else
{
return -1;
}
}
}
static void disparr(ArrayList myarr, string str)
{
Console.WriteLine(str);
Console.WriteLine("\t{0}\t{1}\t{2}", "学号", "姓名", "分数");
foreach (Stud s in myarr)
{
s.disp();
}
}
static void Main(string[] args)
{
int i, n = 4;
IComparer myComparerxh = new myCompareClassxh();
IComparer myComparerxm = new myCompareClassxm();
IComparer myComparerfs = new myComparerfs();
ArrayList myarr = new ArrayList();
Stud[] st = new Stud[4]{new Stud(1,"Smith",82),
new Stud(4,"valeb",99),
new Stud(3,"john",78),
new Stud(2,"mary",88)};
for (i = 0; i < n; i++)
{
myarr.Add(st[i]);
}
disparr(myarr, "排序前:");
myarr.Sort(myComparerxh);
disparr(myarr, "按学号升序排序");
myarr.Sort(myComparerxm);
disparr(myarr, "按姓名词典次序排序:");
myarr.Sort(myComparerfs);
disparr(myarr, "按分数排序后:");
}
}
#endregion
#endregion
#region 泛型(的定义和使用)
通常先定义泛型,然后通过类型实例化来使用泛型。
定义泛型语法格式如下:
[访问修饰符][返回类型] 泛型名称<类型参数列表>
其中,“泛型名称”要符合标识的定义,尖括号表示类型参数列表,可以包含一个或多个类型参数。<T,U...>
/*
C#中常用泛型有泛型类、泛型方法。如:
class stack<T>//泛型类
{
T data[MaxSize];
int top;
...
}
void swap<T>(ref T a,ref T b)//泛型方法
{
T tmp=a;
a = b;
b = tmp;
}
*/
class Stack<T> //泛型类
{
T[] data;
int top;
public Stack()//构造函数
{
data=new T[10];
top = -1;
}
public bool StackEmpty()
{
return top == -1;
}
public void Push(T e)
{
top++;
data[top] = e;
}
public void Pop(ref T e)
{
e = data[top];
top--;
}
}
class Program
{
static void Main(string[] args)
{
int e = 0;
Stack<int> s = new Stack<int>();//整数栈
s.Push(1);
s.Push(3);
s.Push(2);
Console.WriteLine("整数栈出栈次序");
while (!s.StackEmpty())
{
s.Pop(ref e);
Console.WriteLine("{0}",e);
}
Console.WriteLine();
string e1 = "";
Stack<string> s1 = new Stack<string>();//字符串栈
s1.Push("valeb");
s1.Push("mary");
s1.Push("john");
Console.WriteLine("字符串栈出次序");
while (!s1.StackEmpty())
{
s1.Pop(ref e1);
Console.WriteLine("{0}",e1);
}
Console.WriteLine();
}
}
#endregion
}
C# 初学者的 转折知识点
最新推荐文章于 2021-08-11 22:51:12 发布