一.Delegate是什么?
Delegate中文翻译为“委托”。Msdn中对Delegate的解释如下:
C#中的委托类似于C或C++中的函数指针。使用委托使程序员可以将方法引用封装在委托对象内。然后可以将该委托对象传递给可调用所引用方法的代码,而不必在编译时知道将调用哪个方法。与C或C++中的函数指针不同,委托是面向对象、类型安全的,并且是安全的。
如果你是第一次接触Delegate这个概念,你可能会对上面这段文字感觉不知所云,不过不要紧,你可以先把Delegate认为就是一个函数指针。
而当你面对一个虚无的概念时,最好的应对方法就是直接看实例。下面一个简单的Delegate使用例子。
class Program
{
static void OtherClassMethod(){
Console.WriteLine("Delegate an other class's method");
}
static void Main(string[] args)
{
var test = new TestDelegate();
test.delegateMethod = new TestDelegate.DelegateMethod(test.NonStaticMethod);
test.delegateMethod += new TestDelegate.DelegateMethod(TestDelegate.StaticMethod);
test.delegateMethod += Program.OtherClassMethod;
test.RunDelegateMethods();
}
}
class TestDelegate
{
public delegate void DelegateMethod(); //声明了一个Delegate Type
public DelegateMethod delegateMethod; //声明了一个Delegate对象
public static void StaticMethod()
{
Console.WriteLine("Delegate a static method");
}
public void NonStaticMethod()
{
Console.WriteLine("Delegate a non-static method");
}
public void RunDelegateMethods()
{
if(delegateMethod != null){
Console.WriteLine("---------");
delegateMethod.Invoke();
Console.WriteLine("---------");
}
}
}
上面是一个Delegate的使用例子,运行看看结果吧。下面我稍微解释一下:
【1】public delegate void DelegateMethod();这里声明了一个Delegate的类型,名为DelegateMethod,这种Delegate类型可以搭载:返回值为void,无传入参数的函数。
【2】public DelegateMethod delegateMethod;这里声明了一个DelegateMethod的对象(即,声明了某种Delegate类型的对象)。
区分:DelegateMethod是类型,delegateMethod是对象。
【3】为什么上面说Delegate可以看做是函数指针呢?看下面这段代码:
test.delegateMethod = new TestDelegate.DelegateMethod(test.NonStaticMethod);
test.delegateMethod += new TestDelegate.DelegateMethod(TestDelegate.StaticMethod);
test.delegateMethod += Program.OtherClassMethod;
这里delegateMethod搭载了3个函数,而且可以通过调用delegateMethod.Invoke();运行被搭载的函数。这就是Delegate可以看作为函数指针的原因。上面这段代码中,delegateMethod只能搭载:返回值为void,无传入参数的函数(见:NonStaticMethod,StaticMethod,OtherClassMethod的定义),这和Delegate类型声明有关(见DelegateMethod的声明:public delegate void DelegateMethod())。
【4】Delegate在搭载多个方法时,可以通过+=增加搭载的函数,也可以通过-=来去掉Delegate中的某个函数。
C#的Enum——枚举
枚举
枚举类型声明为一组相关的符号常数定义了一个类型名称。枚举用于“多项选择”场合,就是程序运行时从编译时已经设定的固定数目的“选择”中做出决定。
枚举类型(也称为枚举)为定义一组可以赋给变量的命名整数常量提供了一种有效的方法。例如,假设您必须定义一个变量,该变量的值表示一周中的一天。该变量只能存储七个有意义的值。若要定义这些值,可以使用枚举类型。枚举类型是使用 enum 关键字声明的。
枚举的优点:
1、枚举可以使代码更易于维护,有助于确保给变量指定合法的、期望的值。
2、枚举使代码更清晰,允许用描述性的名称表示整数值,而不是用含义模糊的数来表示。
3、枚举使代码更易于键入。在给枚举类型的实例赋值时,VS.NET IDE会通过IntelliSense弹出一个包含可接受值的列表框,减少了按键次数,并能够让我们回忆起可能的值
枚举实例
声明:
{
Moning = 0,
Afternoon = 1,
Evening = 2,
};
使用:
{
string result = string.Empty;
switch (time)
{
case TimeOfDay.Moning:
result = "上午";
break;
case TimeOfDay.Afternoon:
result = "下午";
break;
case TimeOfDay.Evening:
result = "晚上";
break;
default:
result = "未知";
break;
}
return result;
}
枚举方法
1、获取枚举字符串
Console.WriteLine(time.ToString());//输出:Afternoon
2、Enum.Parse()方法。这个方法带3个参数,第一个参数是要使用的枚举类型。其语法是关键字typeof后跟放在括号中的枚举类名。typeof运算符将在第5章详细论述。第二个参数是要转换的字符串,第三个参数是一个bool,指定在进行转换时是否忽略大小写。最后,注意Enum.Parse()方法实际上返回一个对象引用——我们需要把这个字符串显式转换为需要的枚举类型(这是一个取消装箱操作的例子)。对于上面的代码,将返回1,作为一个对象,对应于TimeOfDay.Afternoon的枚举值。在显式转换为int时,会再次生成1。
Console.WriteLine((int)time2);//输出1
3、得到枚举的某一值对应的名称
两种方法都能实现,但是当其值越界(不是枚举所列出的值),就有一定的区别了。大家可以根据自己的需求不同,选择合适的方法。
this.lbGetName.Text = Enum.GetName(typeof(TimeOfDay), 5); //返回:空字符串,如果越界返回空字符串
4、得到枚举的所有的值
lbValues.Text += i.ToString();
5、枚举所有的名称
lbNames.Text+=temp;
interface接口:
接口是把公共实例(非静态)的方法和属性结合起来,以封装特定功能的一个集合,一旦定义了接口,就可以在类中使用实现接口中的所有成员,接口可以看作创建者和使用者之间的契约,一旦实现了接口,就不要轻易变动(如果需要变更接口,一般需要继承旧接口并且添加版本号)。我们知道在C++里面是有纯虚函数,虚继承和多重继承的,C#里面为了简化C++的这些复杂的设施,引出了接口这个概念。
public class Starter { /// <summary> /// 程序入口点 /// </summary> /// <param name="args"></param> public static void Main(string[] args) { Fuck test = new Fuck(); } } public interface IFuck { void Haha(); } public class Fuck :IFuck { void IFuck.Haha() { } }