笔试三(面试)

1.介绍ASP.NET?

ASP.NET不是一种语言,而是动态创建WEB页的一种强大的服务器技术。他是.net framework中一套用于生成web应用程序和web服务的技术。

ASP.NET页面由事件驱动,页面与逻辑相隔离

2.说明ASP.NET的Application特性?

Application用于保存所有用户公用信息,范围是整个应用程序域。在ASP.NET环境中,在web.config中配置。如果要写Application,则在Global.asax中的Application_OnStart事件中完成。

//下面代码在Global.asax中设置
Application.Lock();
Application["UserID"]="hello";
Application.UnLock();

//以下是在webpage中调用
String User =(Application["UserID"]??0).toString();
View Code

 Application有以下4个特性:

1信息量大小为任意大小,2应用于整个应用程序域\所有用户,3保存在服务起端,4作用域和保存时间在整个应用程序的生命周期

由于Global.asax中串行化对Application请求,所以不能保存大量数据

3.简述ASP.NET页面运行机制?

当第一次访问页面时,页面请求首先一次经过HttpModuls和HttpHandler的处理,服务器接收到HttpHandler的请求后将页面跳转到需要访问的页面。

然后ASP.NET引擎负责找到这个后台类,并实例化一个临时对象。在此过程中会触发一系列事件,一部分事件需要进过对象中的方法进行处理,之后服务器会将这个处理后的页面交给Response对象,然后由Response对象将这个页面发送到客户端

当再次访问页面的时候,由于临时对象已经建立,不用再重复建立页面初始化,故第二次直接提交HttpModuls和HttpHandler,直接与临时对象交互并返回。

当涉及到需要调用Cache时,临时对象直接从ASP.NET缓存中提取信息并返回

当页面刷新的时候,服务器发现这个请求处理过(处理时会把处理结果放在默认的HttpModuls管理的输出缓存),则直接取该缓存数据。

4.简述ASP.NET一个页面的生命周期? 

1.页面生命周期的主要阶段包括: 阶段 事件/方法
页面初始化          Page_Init  
加载View State      LoadViewState   
回发数据处理      LoadPostData   
页面加载          Page_Load   
回发通知          RaisePostDataChangedEvent  
回发事件处理     RaisePostBackEvent  
页面预渲染       Page_PreRender   
保存             viewstate SaveViewState   
Page渲染         Page_Render   
Page 卸载       Page_UnLoad 
2.页面生命周期的主要事件:

PreInit:

1.检查IsPostBack 属性

2.动态设置Master Page

3.动态设置Theme

4.设置控件的默认值(UniqueId等)

5.重新创建动态控件(初始化控件),初始化控件的值

Init: 这个事件发生在所有的控件被初始化,所有的皮肤设置被应用以后。它用来读取或者初始化控件属性。它能够用来注册一些aspx页面中没有指出的控件的事件。

InitComplete: Use this event for processing tasks that require all initialization to be complete.

PreLoad: 加载页面的ViewState和所有的控件,然后处理所有的包含在Request实例中的postback数据。

Load: 这个事件可能是大家最熟悉的了。需要注意的是,Page对象会递归的调用子控件的onload事件直到页面和所有的子控件被加载完成。这个事件主要用来设置控件属性的值,建立数据库连接(通常不这么做)。

Validation: 如果你的控件要求验证,验证会在这个阶段发生,这个时候你可以检查控件的IsValid属性。跟这个阶段关联的事件是Validate,它有一个可以接受验证字符串群的重载方法(overload method),这个重载方法执行特定控件群的验证。

Control events: 这个就不多说了,主要是处理控件的事件,例如click。这也就让我们明白了每次我们click一个Button的时候,实际上是要先去执行load事件然后才执行click事件的,一般我们用!IsPostBack来判断一下从而避免执行不必要的加载逻辑。

LoadComplete: 页面所有的控件都被加载以后执行,暂时没有想到用来干什么。。。

PreRender: 在HTML被生成之前这是最后一个事件。每一个页面中的控件都有PreRender的过程。在这里对将要输出的HTML结果进行最后一次修改。

SaveStateComplete: 在这个时间发生之前,已经保存了所有控件和页面的,任何对page或者控件的改动都不会产生左右。暂时没想到用来干啥。

Render: 它不是一个事件而是一个方法。工作就是把HTML写回客户端浏览器。

UnLoad: 页面中的每一个控件都会发生这件事。在控件中,使用这个事件来做清理工作,例如关闭数据库连接等。对与页面本身也是做清理工作,例如关闭打开的文件和数据库连接,或者结束日志或者其它指定的工作。

需要说明的是,每次Request都会创建一个全新的Page类的实例,所以在页面中的自己定义的字段是不能在两次request中传递值的,需要使用viewstate来存储。
View Code

5.C#托管代码和非托管代码是什么?

托管代码(Managed Code)实际上就是中间语言(IL)代码。

代码编写完毕后进行编译,此时编译器把代码编译成中间语言(IL),而不是能直接在你的电脑上运行的机器码。

程序集(Assembly)的文件负责封装中间语言,程序集中包含了描述所创建的方法、类以及属性的所有元数据。

当某些方法被调用时,公共语言运行库把具体的方法编译成适合本地计算机运行的机器码,并且将编译好的机器码缓存起来,以备下次调用时使用。这个过程就是即时编译。

注意:程序实际上是被“托管”在公共语言运行库中。随着程序集的运行,公共语言运行库会持续地提供各种服务,例如内存管理、安全管理、线程管理等等。

总结:

托管代码(Managed Code)是由公共语言运行库(CLR)执行的代码,而不是由操作系统直接执行。

托管代码也可以调用CLR的运行库服务和功能,比如GC、类型检查、安全支持等等。这些服务和功能提供独立与开发语言的、统一的Managed Code应用程序行为。
View Code
非托管代码(Unmanaged Code)是指直接编译成目标计算机的机器码,这些代码只能运行在编译出这些代码的计算机上,或者是其他相同处理器或者几乎一样处理器的计算机上。
非托管代码不能享受公共语言运行库所提供的一些服务,例如内存管理、安全管理等。
如果非托管代码需要进行内存管理等服务,就必须显式地调用操作系统的接口,通常非托管代码调用Windows SDK所提供的API来实现内存管理。
非托管程序也可以通过调用COM接口来获取操作系统服务。
注意:C#跟Visual Studio平台的其他编程语言不一样的是,C#可以创建托管程序与非托管程序。当创建的项目选择名字以MFC,ATL或者Win32开头的项目类型,那么这个项目所产生的就是非托管程序。
总结:非托管代码(Unmanaged Code)不由CLR公共语言运行库执行,而是由操作系统直接执行的代码。
View Code

6.C#支持哪几个预定义的值类型?

整型(int32,byte等),浮点类型(single,double),字符型(Char),布尔型,decimal型

7.C#支持哪几个预定义的引用类型?

Object和String

8.如何解决拆箱和装箱引发的性能问题?

泛型

9.值类型与引用类型的区别?

10.请举例Hashtable几种常用的遍历方法?

11.System.String是引用类型还是值类型?

由于字符串是只读的,所以对他赋值(String a ="老字符串",a="新字符串"),当他已经初始化过了以后,会生成一个新的字符串对象,并且赋给了引用a.(导致string看起来像值类型的原因

12.C#中String和string区别是什么?

String 是CLR类型名称(关键字),string是C#的关键字

13.Array和ArrayList的区别?

相似点:他们所创建的对象都放在托管堆中,都具有索引(index),都能够对自身进行枚举(因为都实现了IEnumerable接口)

不同点:

 1. Array类型的变量在声明的同时必须进行实例化(至少得初始化数组的大小),而ArrayList可以只是先声明。

 如:
 int[] array = new array[3];
 或 int[] array = {1,2,3};
 或 ArrayList myList = new ArrayList();
这些都是合法的,而直接使用 int[] array;是不行的。
View Code

 2. Array只能存储同构的对象,而ArrayList可以存储异构的对象

同构的对象是指类型相同的对象,若声明为int[]的数组就只能存放整形数据,string[]只能存放字符型数据,但声明为object[]的数组除外。
而ArrayList可以存放任何不同类型的数据(因为它里面存放的都是被装箱了的Object型对象,实际上ArrayList内部就是使用"object[] _items;"这样一个私有字段来封装对象的)
View Code

 3.在CLR托管对中的存放方式

 Array是始终是连续存放的,而ArrayList的存放不一定连续

 4. 初始化大小

Array对象的初始化必须只定指定大小,且创建后的数组大小是固定的,
而ArrayList的大小可以动态指定,其大小可以在初始化时指定,也可以不指定,也就是说该对象的空间可以任意增加。
View Code

 5.Array不能够随意添加和删除其中的项,而ArrayList可以在任意位置插入和删除项

14.C#中is和as运算符有什么作用?

is:1.检查对象类型的兼容性,并返回结果true(false),2.不会抛出异常,3.如果对象为null,刚返回false

as:1.检查对象类型的兼容性,并返回转换结果,如果不兼容则返回null,2.不会抛出异常,3.如果结果判断为空,则强制执行类型转换将抛出NullReferenceException异常

15.简述C#中的虚方法?

16.简述C#中的密封类和密封方法?

密封类使用sealed关键字进行修饰,它不能用作其他类的基类,并且它没有派生类

密封方法(sealed)是使用sealed关键字进行修饰的方法,它并不影响类的继承,但它可以防止重写基类中特定的虚方法

class A  
{  
    protected virtual void F() 
   { Console. WriteLine("A.F");}//定义一个虚方法  
}  
class B : A  
{  
    sealed protected override void F() {
    Console.WriteLine("B.F");}  //定义密封方法  
}  
class C : B  
{  
    //下面是一段错误的代码,密封方法不能够重写  
    protected override void F() { Console.WriteLine("C.F"); }  
} 
View Code

17.请介绍C#静态类构造方法的特点?

class StaticSimple  
{  
    public static int k =100;               //定义静态变量  
    static StaticSimple()                   //创建
自定义的静态构造方法  
    {  
        Console.WriteLine("请注意方法的执行顺序。");  
    }  
    //注释的这段代码是错误的代码,在一个类里只允许有一
个无参的静态构造方法  
    //static StaticSimple(String str)  
    //{  
    //  Console.WriteLine("在一个类里只允许有一个
无参的静态构造方法。");  
    //}  
    public StaticSimple()               //定义无
参的构造器,同时给j和s赋值  
    {  
        Console.WriteLine("这是无参构造器");  
    }  
}  
class Program  
{  
    static void Main(string[] args)  
    {  
    //先调用静态成员k的值,结果会是先执行静态构造方
法,再显示k=100 
    Console.WriteLine("读者请注意,在输入k值请是
否有其他的输出。k=" + Static  
    Simple.k);  
    //此时不会再出现static构造器的内容,因为前面已经执行了一次  
    StaticSimple A = new StaticSimple();  
    Console.Read();  
    }  
} 
View Code

通过运行上面的代码可以发现,C#中的构造方法有以下4个特点:

只允许有一个无参的静态构造方法在一个类中存在,静态的构造方法不会被继承,在所有静态成员被引用之前执行静态构造方法,在所有的构造方法中最先被执行的是静态的构造方法

18.介绍C#派生类的构造函数?

class Circle  
{  
    public Circle()                         //默认构造函数  
    {  
        Console.WriteLine("基类无参构造方法。");  
    }  
    public Circle(double initialRadius) //带一个参数的构造函数  
    {  
        Console.WriteLine("基类有参构造方法。");  
    }  
}  
class UnitCircle : Circle                   //派生类  
{  
    public UnitCircle(double unitRadius) :base(unitRadius) {}  
                                            //调用基类的构造函数  
    public UnitCircle():this(1,2)           //调用本类中的构造函数  
    {  
        Console.WriteLine("派生类无参构造方法。");  
    }  
    public UnitCircle(int i,int j)          //定义
一个带两个参数的构造函数  
    {  
        Console.WriteLine("派生类有参构造方法。"+i.ToString());  
    }  
}  
class Program  
{  
    static void Main(string[] args)  
    {  
            UnitCircle u new UnitCircle();    //调用
派生类中的无参构造函数  
        UnitCircle u1 new UnitCircle(2);  
                                        //调用派
生类中的有一个参数的构造函数  
        Console.Read();  
    }  
} 
运行上面的代码,请读者注意base与this这两个关键字的作用:

public UnitCircle(double unitRadius) :base(unitRadius) {} 
派生类中的base关键字表示当调用UnitCircle(double unitRadius)构造函数时,它实际调用的是基类中的Circle(double initialRadius)构造函数。

而派生类中的this关键字表示当调用的构造函数,是本派生类中的构造函数。

public UnitCircle():this(1,2
View Code

19.事件机制

public class ctrEvent  
{  
    //定义一个委托  
    public delegate void SomeHandler(object 
sender, System.EventArgs e);  
    public event SomeHandler SomeEvent;        
//定义一个委托事件  
    public ctrEvent()  
    {  
       this.SomeEvent += new SomeHandler(this.
ProcessSomeEvent);  
                                                    //事件绑定  
    }  
    public void RaiseSomeEvent()  
    {  
        EventArgs e new EventArgs();  
        Console.WriteLine("请输入'Andy'");  
        string s = Console.ReadLine();  
        if (s.ToLower() == "andy")  
        {  
            //请在用户输入一个andy的情况下触发事件,否则不触发  
            SomeEvent(this,e);  
        }  
        else  
        {  
            Console.WriteLine("错误的输入");  
        }  
    }  
    private void ProcessSomeEvent(object sender, EventArgs e)  
    {  
        Console.WriteLine("你好");  
    }  
} 
为了演示事件的响应,以下示例代码定义了一个ResponseSomeEvent()方法。当控制台事件被触发发生时,该类型对象将向控制台输出的内容。

using System;  
namespace MyConsole  
{  
    //事件的接收者(事件的响应)  
    class Container  
    {  
        private ctrEvent ctrEvent1 = new ctrEvent(); //初始化ctrEvent对象  
        public Container()  
        {  
            //将事件绑定到相应方法ResponseSomeEvent()  
            ctrEvent1.SomeEvent += new ctrEvent.SomeHandler(this.Response  
            SomeEvent);  
            //调用RaiseSomeEvent()方法,当输入正确的口令就会出发事件  
            ctrEvent1.RaiseSomeEvent();  
        }  
        public static void Main()  
        {  
            Container pane new Container();        //初始化Container  
            Console.ReadLine();  
        }  
        //接收者对事件的响应  
        private void ResponseSomeEvent(object sender, EventArgs e)  
        {  
            Console.WriteLine("事件响应,也就是事件发生了");  
        }  
    }  
} 
代码执行结果如下:

请输入'Andy'  
Andy  
你好  
事件响应,也就是事件发生了 
View Code

20.列举一个委托和事件的实例

一个公司(场景),笔者是老板,手下有两个员工,小赵和小李。你命令小赵,如果小李玩游戏,则小赵扣去小李400元钱。这就是现实中的委托。实际上,在写程序中,程序员就是老板,小赵和小李就是两个对象。小李玩游戏是一个方法,小李还有一个游戏事件,小李玩游戏激发这个事件。而小赵就是事件处理对象,小赵负责把小李的钱扣除400。

所以,委托有如下几个要素:

激发事件的对象:就是小李。

处理对象事件的对象:就是小赵。

定义委托:就是你让小赵监视小李。

//负责扣钱的人  
public class Zhao  
{  
    public Zhao()  
    {  
        Console.WriteLine("生成小赵");  
    }  
    public void DeductMoney(object sender, EventArgs e)  
    {  
        Console.WriteLine("小赵:好小子,上班时间胆敢玩游戏...");  
        Console.WriteLine("小赵:你不知道上班打游戏要罚款吗?);  
        Li f = (Li)sender;                          //发送事件  
        Console.WriteLine("小李的工资: " + f.Money.ToString());  
        Console.WriteLine("开始扣钱...");  
        System.Threading.Thread.Sleep(500);     //延迟  
        ff.Money= f.Money- 400;                  //扣除工资  
        Console.WriteLine("扣完了...现在小李还剩下:" + f.Money.ToString());  
    }  
} 
接着创建小李这个对象,代码如下:

//如果玩游戏,则引发事件  
public class Li  
{  
    //先定义一个事件,这个事件表示小李在玩游戏  
    public event PlayGameHandler PlayGame;  
    //保存小李钱的变量  
    private int m_Money;  
    public Li()  
    {  
        Console.WriteLine("生成小李...");  
        m_Money = 2000;                       
//构造函数,初始化小李的钱  
    }  
    public int Money                        //此属性可以操作小李的钱  
    {  
        get  
        {  
            return m_Money;  
        }  
        set  
        {  
            m_Money = value;  
        }  
    }  
    public void Game()  
    {  
        Console.WriteLine("小李开始Game了...");  
        Console.WriteLine("小李:魔兽好玩,哈哈哈! 我玩...");  
        System.Threading.Thread.Sleep(500);     //延迟  
        System.EventArgs e = new EventArgs();       //创建新事件  
        //OnPlayGame(e);  
        if (PlayGame != null)  
        {  
            PlayGame(this, e);  
        }  
    }  
    protected virtual void OnPlayGame(EventArgs e)  
 //重写基类的OnPlayGame()方法  
    {  
        if (PlayGame != null)  
        {  
            PlayGame(this, e);  
        }  
    }  
} 
当这两个对象建立完成后,运行主程序触发事件,代码如下:

namespace MyConsole  
{  
    //定义委托处理程序  
    public delegate void PlayGameHandler(object 
sender, System.EventArgs e);  
    public class BackgroundEvent  
    {  
        [STAThread]  
        public static void Main(string[] args)  
        {  
            Console.WriteLine("场景开始了...");  
            //生成Zhao  
            Zhao z = new Zhao();  
            //生成Li  
            Li l = new Li();  
            l.PlayGame += new PlayGameHandler(z.
DeductMoney);   //指定监视  
            l.Game();                                 
//开始Game  
            Console.WriteLine("场景结束...");  
            Console.ReadLine();  
        }  
    }  
} 
运行结果如下:

场景开始了...  
生成小赵  
生成小李...  
小李开始Game了...  
小李:魔兽好玩,哈哈哈! 我玩...  
小赵:好小子,上班时间胆敢玩游戏...  
小赵:你不知道上班打游戏要罚款吗?  
小李的工资:2000  
开始扣钱...  
扣完了...现在小李还剩下1600  
场景结束... 
【答案】

正如本小节代码所示,程序员定义了一个事件时,事实上是定义了一个特定的委托成员。该委托没有返回值,并且拥有两个参数:object sender和EventArgs e。而当事件使用者订阅事件时,本质上就是把事件处理方法加入委托链表之中。希望读者认真地阅读理解本小节的代码实例,在实际的开发设计中能更好地运用事件以及委托的特性。
View Code

21.请简述EventHandlerList的作用

// 类MyControl定义了两个事件属性,MouseUp和MouseDown  
class MyControl: Component {  
   // 定义其他控制方法和属性  
 
   protected EventHandlerList listEventDelegates 
new EventHandlerList();                              
// 定义委托的集合  
   static readonly object mouseDownEventKey = new object();  
                                               
// 为每一个活动的独特的关键  
   static readonly object mouseUpEventKey = new object();  
 
   //定义MouseDown事件属性  
   public event MouseEventHandler MouseDown {  
      // 输入委托添加到集合  
      add { listEventDelegates.AddHandler
(mouseDownEventKey, value); }  
      // 从集合中删除输入的委托  
      remove { listEventDelegates.RemoveHandler
(mouseDownEventKey,  
      value); }  
   }  
   // MouseUp事件定义属性  
   public event MouseEventHandler MouseUp {  
      //输入委托添加到集合  
      add { listEventDelegates.AddHandler(mouseUpEventKey, value); }  
      // 从集合中删除输入的委托  
      remove { listEventDelegates.RemoveHandler
(mouseUpEventKey, value); }  
   }  
} 
注意:可以使用EventHandlerList类或实现自定义的集合。例如可以使用Hashtable类或从 DictionaryBase类派生一个自定义类,不需要在类以外公开委托集合的实现详细信息。

【答案】

EventHandlerList最主要的作用就是提供一个存储事件的集合,程序员可以方便地将某个类型中多个事件维护在EventHandlerList集合中,而不需要独立的维护每一个事件。
View Code

22.什么是委托?

委托是一种引用类型,它是函数指针的托管版本。在C#中,委托是一种可以把引用存储为函数的类型。委托可以引用实例和静态方法,而函数指针只能引用静态方法。委托的声明非常类似函数,和函数不同的是委托不带函数体,并且需要使用Delegate关键字。委托的声明指定了一个函数签名,其中包含参数列表和一个返回类型。在定义了委托后,就可以声明该委托类型的变量,然后可以将这个变量初始化为与该委托有相同签名的函数进行引用,随后可以使用委托变量调用该函数。

注意:委托虽然与函数指针非常类似,但却不是指针。许多程序员把.NET中的委托理解为安全的函数指针,这样的理解是比较牵强的,委托实现的功能和函数指针非常类似的一点就是提供了程序回调机制。

委托的内部实现机制和函数指针在指向方法这一点上是完全相同的。委托是安全的,主要因为委托和其他所有的.NET成员一样,均是一种类型,都是System.Delegate的某个派生类的一个对象。

using System;  
namespace MyConsole  
{  
    class SimpleDelegate  
    {  
        //定义一个返回为double类型的委托,这个委托有一个整型的输入参数  
        public delegate double Delegate_Prod(int a);  
        static double fn_Prodvalues(int val1)  
        {  
            return val1 * val1;  
        }  
        static void Main(string[] args)  
        {  
Delegate_Prod delObj new Delegate_Prod(fn_Prodvalues);  
                                                //声明一个委托  
            Console.Write("请输入数字");  
            int v1 = Int32.Parse(Console.ReadLine());  
//输入一个整型数值  
            double res = delObj(v1);               
//调用委托方法fn_Prodvalues  
            Console.WriteLine("返回值:" + res);            //返回结果  
            Console.ReadLine();  
        }  
    }  
} 
示例代码中,首先通过public delegate double Delegate_Prod(int a)定义了一种名为Delegate_Prod的新类型,这个类型继承自System.MulticastDelegate。它包含一个名为Invoke()的方法,该方法接收一个字符型的参数且没有任何返回。这些步骤都是由C#编译器自动完成的。然后,声明了一个Delegate_Prod的对象delObj,并且绑定到fn_Prodvalues这个静态方法上。运行结果如下:

请输入数字9  
返回值: 81 
注意:本质上,委托的调用就是执行了在定义委托时所生成的Invoke()方法。

C#中的委托类都继承自System.Delegate类型。委托类型的声明与方法签名相似,有一个返回值和任意数目任意类型的参数。委托是一种可用于封装命名或匿名方法的引用类型。委托类似于函数指针,但是委托是类型安全和可靠的。
View Code

23.C#中被委托的方法必须是静态的吗?

静态方法和实例方法的区别?

              静 态 方 法             实 例 方 法
Static关键字 不需要static关键字
类名调用 实例对象调用
可以访问静态成员 可以直接访问静态成员
不可以直接访问实例成员,需要实例化 可以直接访问实例成员
不能直接调用实例方法,需要实例化 可以直接调用实例方法和静态方法
调用前初始化 实例化时初始化
委托绑定实例方法的分析,依据C#实例方法的定义,当一个实例方法被调用时,需要通过实例对象来访问,因此绑定实例方法到委托时,必须同时让委托得到该实例方法的实例对象的信息。这样,.NET才能在委托被回调(CallBack)的时候成功地执行该实例方法。Delegate.Target属性是一个指向目标实例的引用,当绑定实例方法给委托时,该参数会被设置为该方法所在类型的一个实例对象。

委托绑定静态方法的分析。Delegate.Target属性是一个指向目标实例的引用,当绑定一个静态方法给委托时,则该参数会被设置为null。

注意:如果委托调用一个或多个实例方法,则此属性返回调用列表中最后一个实例方法的目标
View Code

委托不仅能绑定静态方法,同时也可绑定实例方法。当绑定实例方法时,Delegate.Target属性将会设置成指向该实例方法所属类型的一个实例对象,当绑定静态方法时,Delegate.Target属性将会被设置成null

24.什么是多播委托?

所谓的多播委托,是指引用多个方法的委托,当调用委托时,它连续调用每个方法。在调用过程中,委托必须为同类型,返回类型也必须是void,且不能带输出参数(但可以带引用参数),这样才能将委托的单个实例合并为一个多播委托。

using System;  
namespace MyConsole  
{  
    class MulticastDelegate  
    {  
        //定义委托,接收一个字符型参数  
        public delegate void hellokittyHander(string msg);  
        private void hellokitty1(string msg)  
                                    //定义一个简单
的私有方法hellokitty1()  
        {  
            Console.WriteLine("hello kitty1" + msg);  
        }  
        private void hellokitty2(string msg)  
                                    //定义一个简单
的私有方法hellokitty2()  
        {  
            Console.WriteLine("hello kitty2" + msg);  
        }  
        private void hellokitty3(string msg)  
                                    //定义一个简单的
私有方法hellokitty3()  
        {  
            Console.WriteLine("hello kitty3" + msg);  
        }  
        static void Main(string[] args)  
        {  
            MulticastDelegate SimpleDelegate new
 MulticastDelegate();  
            //声明一个委托变量,并绑定第一个方法  
            hellokittyHander hellokitty = new 
hellokittyHander(SimpleDele-  
            gate.hellokitty1);  
hellokitty += new hellokittyHander(SimpleDelegate.hellokitty2);  
                            //绑定第二个方法  
hellokitty += new hellokittyHander(SimpleDelegate.hellokitty3);  
                            //绑定第三个方法  
            //删除已经调用委托方法  
            hellokitty -= new hellokittyHander
(SimpleDelegate.hellokitty2);  
            if (hellokitty != null)  
                hellokitty("这是一个委托demo");  
            Console.ReadLine();  
        }  
    }  
} 
简单分析这个例子,示例代码中首先定义了一个带string参数无返回的委托hellokittyHander,在Main()函数中声明了一个hellokittyHander的委托变量hellokitty,并绑定了第一个方法void hellokitty1(string msg)。然后,通过hellokitty += new new hellokittyHander(SimpleDelegate.hellokitty1)初始化了第二个委托,并且绑定了void hellokitty2(string msg) ,同时把第二个委托挂在第一个委托之后。紧接着,挂上第三个委托并绑定到 void hellokitty3(string msg)。这是一种比较简单明了的写法,在开发ASP.NET 或者Windows应用程序时,当一个按钮事件被添加时,Visual Studio就会为程序生成类似的代码。

代码运行结果如下:

hello kitty1 这是一个委托demo  
hello kitty3 这是一个委托demo 
在这里读者可能会对这个输出的代码产生困惑,为什么hello kitty2没有被输出。事实上细心的读者会发现在上面的程序中有一句取消绑定的事件,代码如下:

//删除已经调用委托方法  
hellokitty -= new hellokittyHander
(SimpleDelegate.hellokitty2); 
注意:多播委托是指一个委托的链表,而不是指另一类特殊的委托。当执行链上的一个方法,后续委托方法将会依次被执行。System.MulticastDelegate定义了对多播委托的支持
View Code

多播委托是指一个由委托串成的链表,当链表上的一个委托被回调时,所有链表上该委托的后续委托将会被顺序执行。但要注意,多播委托必须是同类型的,返回类型必须是void,并且不能带输出参数(但可以带引用参数)

25.ASP.NET的Request对象有哪些?

当客户端发出请求执行asp.net程序时,CLR会将客户端的请求信息包含在Request对象中。这些请求信息包括请求报头,客户端的基本信息(如浏览器类型,浏览器版本号,用户所用的语言以及编码方式等),请求方法(如post,get),参数名,参数值等

1.QueryString集合收集的信息来源于请求url地址中"?"号后面的数据,这些数据称作url附加信息。例如,www.sina.com/show.asp?id=111 
在此url中,QueryString收集到的信息是"show.asp?"后面的数据"id=111"。此时,取得参数"id"的参数值的语句为:Request.QueryString["id"]; 
QueryString主要用于收集http协议中get请求发送的数据,如果在一个请求事件中被请求的程序url地址出现了"?"号后的数据,则表示此次请求方式为get。get方法是http中的默认请求方法。 
那么,如何发送get请求方法呢? 
(1)<a href="show.aspx?id=111">显示ID为111的文章</a> 
   (2)<form action="show.aspx" method="get"> 
     <input type="text" name="id" value="111"> 
     </form> 
下面演示一个例子,这个例子中有两个程序,分别是form1.htm和GetInfo1.aspx,其中form1.htm发送get请求,GetInfo1.aspx接收get请求。 
/////////////////////////////////////////////////// 
form1.htm 
/////////////////////////////////////////////////// 
<HTML> 
<HEAD> 
<TITLE> 发送GET请求</TITLE> 
</HEAD> 
<BODY> 
<center> 
发送GET请求 
<hr> 
<form action="GetInfo1.aspx" method="get"> 
您的大名:<input type="text" name="nickname"><br> 
<input type="submit" value="发送"> 
<form> 
</center> 
</BODY> 
</HTML> 
////////////////////////////////////////// 
GetInfo1.aspx 
////////////////////////////////////////// 
<% @ Page Language="C#" %> 
<html> 
<head> 
<title>接收GET请求</title> 
</head> 
<body> 
<center> 
接收GET方法传来的值: 
<hr> 
<% 
      string NickName = Request.QueryString["nickname"];<%--接收参数值--%> 
      Response.Write("GET方法传来的nickname的值为:"+NickName); 
%> 
</center> 
</body> 
</html> 
2.get方法是将传递的数据追加至url中。url地址长度是有限制的,因此使用get方法所能传递的数据也是有限的。一般地,get方法能够传递 256字节的数据,在多数情况下,使用get方法传递的数据长度是远远不够的,这时便需要使用http的另外一种请求方式post,post方法可传递的 数据的最大值为2MB。 
post请求必须由form发出。而且,在使用post请求方法的时候,需要将"method"设置为"post"。asp.net使用Request.Form方法接收post方法传递的数据:Request.Form["Variable"]; 
接下来也举两个例子,来说明post方法的使用,类似于上面的例子,注意对比。 
////////////////////////////////////////////// 
form2.htm//发送post请求 
////////////////////////////////////////////// 
<HTML> 
<HEAD> 
<TITLE> 发送POST请求</TITLE> 
</HEAD> 
<BODY> 
<center> 
发送POST请求 
<hr> 
<form action="GetInfo2.aspx" method="post"> 
您的大名:<input type="text" name="nickname"><br> 
<input type="submit" value="发送"> 
<form> 
</center> 
</BODY> 
</HTML> 
////////////////////////////////////////////////// 
GetInfo2.aspx//接收post请求 
////////////////////////////////////////////////// 
<% @ Page Language="C#" %> 
<html> 
<head> 
<title>接收POST请求</title> 
</head> 
<body> 
<center> 
接收POST方法传来的值: 
<hr> 
<% 
      string NickName = Request.Form["nickname"]; 
      Response.Write("POST方法传来的nickname的值为:"+NickName); 
%> 
</center> 
</body> 
</html> 
3.cookie的使用在后面再讲。 
4.ServerVariable 
ServerVariable(环境变量)包含了客户机和服务器的系统信息。获得环境变量值的方法是:Request.ServerVariables["Variable"]; 
Variable参数            含义 
HTTP_USER_AGENT          获得用户使用的浏览器类型和版本 
REMOTE_ADDR              获取用户的IP地址 
REQUEST_METHOD          获取请求的方法 
LOCAL_ADDR                获取服务器的IP地址 
SERVER_NAME              获取服务器的主机名 
PATH_INFO                  获取当前执行程序的虚拟路径 
PATH_TRANSLATED          获取当前执行程序的绝对路径 
CONTENT_LENGTH          获取请求程序所发送内容的字符总数 
CONTENT_TYPE              获取请求的信息类型 
GATEWAY_INTERFACE        获取网关接口 
QUERY_STRING              获取url的附加信息 
SCRIPT_NAME                获取当前程序的文件名(包含虚拟路径) 
SERVER_PORT                获取服务器接受请求的端口 
SERVER_PROTOCOL          获取服务器遵从的协议以及版本号 
HTTP_ACCEPT_LANGUAGE    获取用户所使用的语言 
最后举一个关于ServerVariable的例子,这个例子的结果也可作为日后查阅ServerVariable集合的原始资料。 
///////////////////////////////////////////////////////// 
<% @ Page Language="C#" %> 
<% @ Import Namespace="System.Data" %> 
<Script Language="C#" Runat="Server"> 
public void Page_Load(Object src,EventArgs e) 
{ 
      //取得ServerVariables变量集合 
      NameValueCollection ServerVariables = Request.ServerVariables; 
      
      //产生一个数据集合,它的用法,我们后面再讨论 
      DataTable dt = new DataTable(); 
      DataRow dr; 

      dt.Columns.Add(new DataColumn("环境变量",typeof(string))); 
      dt.Columns.Add(new DataColumn("变量值",typeof(string))); 


      foreach(string SingleVariable in ServerVariables) 
      { 
            dr = dt.NewRow(); 
            dr[0] = SingleVariable; 
            dr[1] = ServerVariables[SingleVariable].ToString(); 
            dt.Rows.Add(dr); 
      } 

      DataGrid1.DataSource = new DataView(dt); 
      DataGrid1.DataBind(); 
} 
</script> 
<html> 
<head> 
<title></title> 
</head> 
<body> 
<ASP:DataGrid id="DataGrid1" runat="server" 
BorderColor="black" 
BorderWidth="1" 
GridLines="Both" 
CellPadding="3" 
CellSpacing="0" 
Font-Name="Verdana" 
Font-Size="8pt" 
HeaderStyle-BackColor="#aaaadd" 
AlternatingItemStyle-BackColor="#eeeeee" 
/> 
</body> 
</html> 
////////////////////////////////////// 
5.Request的Browser对象 
Request.Browser.Browser//检测浏览器的类型 
Request.Browser.Version//检测浏览器的版本 
Request.Browser.ActiveXControls//检测浏览器是否支持ActiveX控件 
Request.Browser.Cookies//检测浏览器是否支持Cookies 
Request.Browser.VBScript//检测浏览器是否支持VBScript 
下面这个例子说明Browser所有能够访问的属性。 
//////////////////////////////////////////////////////////// 
<html> 
<head> 
<script runat="server" language="c#"> 
   public void Page_Load(Object Source, EventArgs E) 
   { 
     HttpBrowserCapabilities bc= Request.Browser; 

     Welcome.Text = "您好,您正在使用 " + bc.Browser + " v." + bc.Version + ",你的运行平台是 " + bc.Platform ; 


     ActiveXControls.Text = bc.ActiveXControls.ToString(); 
     AOL.Text = bc.AOL.ToString(); 
     BackgroundSounds.Text = bc.BackgroundSounds.ToString(); 
     Beta.Text = bc.Beta.ToString(); 
     Browser.Text = bc.Browser.ToString(); 
     CDF.Text = bc.CDF.ToString(); 
     Cookies.Text = bc.Cookies.ToString(); 
     Crawler.Text = bc.Crawler.ToString(); 
     Frames.Text = bc.Frames.ToString(); 
     JavaApplets.Text = bc.JavaApplets.ToString(); 
     JavaScript.Text = bc.JavaScript.ToString(); 
     MajorVersion.Text = bc.MajorVersion.ToString(); 
     MinorVersion.Text = bc.MinorVersion.ToString(); 
     Platform.Text = bc.Platform.ToString(); 
     Tables.Text = bc.Tables.ToString(); 
     Type.Text = bc.Type.ToString(); 
     VBScript.Text = bc.VBScript.ToString(); 
     Version.Text = bc.Version.ToString(); 
     Win16.Text = bc.Win16.ToString(); 
     Win32.Text = bc.Win32.ToString(); 
   } 
</script> 
<style> 
body{font-size:9pt} 
td{font-size:9pt} 
</style> 
</head> 
<body> 
<form runat="server" method="post"> 
您的浏览器信息已经完全在我们的掌握中了^&^:<br> 
<asp:Label runat="server" id="Welcome" Font-Bold="True" /> 
<table border="1" width="400" bordercolor="black"> 
<tr bgcolor="skyblue"> 
<td width="50%"><b>浏览器属性<b></td> 
<td width="50%"><b>检测结果<b></td> 
</tr> 
<tr > 
<td width="50%">ActiveXControls:</td> 
<td width="50%"><asp:Label runat="server" id="ActiveXControls" /></td> 
</tr> 
<tr bgcolor="skyblue"> 
<td width="50%">AOL:</td> 
<td width="50%"><asp:Label runat="server" id="AOL" /></td> 
</tr> 
<tr > 
<td width="50%">BackgroundSounds:</td> 
<td width="50%"><asp:Label runat="server" id="BackgroundSounds" /></td> 
</tr> 
<tr bgcolor="skyblue"> 
<td width="50%">Beta:</td> 
<td width="50%"><asp:Label runat="server" id="Beta" /></td> 
</tr> 
<tr > 
<td width="50%">Browser:</td> 
<td width="50%"><asp:Label runat="server" id="Browser" /></td> 
</tr> 
<tr bgcolor="skyblue"> 
<td width="50%">CDF:</td> 
<td width="50%"><asp:Label runat="server" id="CDF" /></td> 
</tr> 
<tr > 
<td width="50%">Cookies:</td> 
<td width="50%"><asp:Label runat="server" id="Cookies" /></td> 
</tr> 
<tr bgcolor="skyblue"> 
<td width="50%">Crawler:</td> 
<td width="50%"><asp:Label runat="server" id="Crawler" /></td> 
</tr> 
<tr> 
<td width="50%">Frames:</td> 
<td width="50%"><asp:Label runat="server" id="Frames" /></td> 
</tr> 
<tr bgcolor="skyblue"> 
<td width="50%">JavaApplets:</td> 
<td width="50%"><asp:Label runat="server" id="JavaApplets" /></td> 
</tr> 
<tr> 
<td width="50%">JavaScript:</td> 
<td width="50%"><asp:Label runat="server" id="JavaScript" /></td> 
</tr> 
<tr bgcolor="skyblue"> 
<td width="50%">MajorVersion:</td> 
<td width="50%"><asp:Label runat="server" id="MajorVersion" /></td> 
</tr> 
<tr> 
<td width="50%">MinorVersion:</td> 
<td width="50%"><asp:Label runat="server" id="MinorVersion" /></td> 
</tr> 
<tr bgcolor="skyblue"> 
<td width="50%">Platform:</td> 
<td width="50%"><asp:Label runat="server" id="Platform" /></td> 
</tr> 
<tr> 
<td width="50%">Tables:</td> 
<td width="50%"><asp:Label runat="server" id="Tables" /></td> 
</tr> 
<tr bgcolor="skyblue"> 
<td width="50%">Type:</td> 
<td width="50%"><asp:Label runat="server" id="Type" /></td> 
</tr> 
<tr> 
<td width="50%">VBScript:</td> 
<td width="50%"><asp:Label runat="server" id="VBScript" /></td> 
</tr> 
<tr bgcolor="skyblue"> 
<td width="50%">Version:</td> 
<td width="50%"><asp:Label runat="server" id="Version" /></td> 
</tr> 
<tr> 
<td width="50%">Win16:</td> 
<td width="50%"><asp:Label runat="server" id="Win16" /></td> 
</tr> 
<tr bgcolor="skyblue"> 
<td width="50%">Win32:</td> 
<td width="50%"><asp:Label runat="server" id="Win32" /></td> 
</tr> 
</table> 
</form> 
</body> 
</html> 
////////////////////////////////////////////////////////////////// 
6.其它Request属性和方法 
FilePath          取得当前请求的文件路径 
HttpMethod      取得当前请求的方法 
Files            关乎文件的上传,后面会讲解 
Params          获得QueryString+Form+ServerVariable+Cookies的集合 
TotalBytes      请求内容的大小 
Url              获得url信息 
UserHostAddress 取得用户的IP地址 
UserHostName    取得用户的主机名 
UserLanguages    取得用户所用语言
View Code

(引用来源http://www.cnblogs.com/wf5360308/articles/1641360.html)

26.ASP.NET的Response对象?

Response对象用于向客户端浏览器发送数据,用户可以使用该对象将服务器的数据以html格式发送到用户端浏览器,它与Request组成了一对接受、发送数据的对象,这也是实现动态的基础。
Response对象用来访问所创建的并返回客户端的响应,输出信息到客户端。它提供了表示服务器和性能的http变量。
Response对象的常用属性和方法:

1、Buffer属性
该属性用于指定页面输出时是否要用到缓冲区,默认值是false,当它为true时,直到整个动态网页执行结束
后才会将结果输出到浏览器上。如:
<%Response Buffer="true"%>
<html>
<head><title>Buffer示例</title></head>
<body>
<% 
for i=1 to 50
   Response.write(i & "<br>")
next
%>
</body>
</html>
这个页面执行时,整个主页的所有内容会同时显示在浏览器上,这个主页会存在缓存区中直到脚本执行结束。
2、Cookies属性
该属性传回请求的httpCookieCollection对象集合。
3、Expires属性
该属性用于设置浏览器缓存页面的时间长度(单位为分),必须在服务器段刷新。通过如下设置:
<%Response Expires=0%>通过在asp.net文件中加入这一行代码,要求每次请求是刷新页面,因为Response一收到页面就会过期。
4、Write方法
该方法把数据发送到客户端浏览器,如:<%Response.Write"Hello World"%>
5、Redirect方法
该方法使浏览器可以重新定位到另一个URL上,这样,当客户端发出web请求时,客户端的浏览器类型已经确定,客户被重新定位到相应的页面。如:
‘用户登录实现程序
sub btn_click(sender as object,e as eventargs)
    Dim conn as new SqlConnection("server=localhost;database=BBS_Data;uid=love;pwd=410926")
       Dim cmd as new SqlCommand("select 用户,密码 from 普通用户 where 用户='" & UId.Text & "' And 密码='" & Psw.Text &"'",conn)
       conn.Open()
       dim dr as SqlDataReader=cmd.ExecuteReader()
       do while dr.Read()
             Response.Redirect("index.aspx")
       loop
       conn.close()
End sub
这个例子当用户信息通过验证以后,按登录按钮提交表单,服务器接到申请后调用index.aspx判断后定位到相应的URL。不过这里有一点要注意,HTTP标题已经被写入到客户端浏览器,任何http标题修改必须在写入页面内容之前,遇到这种问题,可以如下做:
在文件的开始<@page language= >后写:Response Buffer="true"在结尾定:Response Flush
这里Flush是Response的一个方法,它必须时Buffer属性设置为true时才能使用,否则会产生一个运行模式错误。另外一个clear方法也是用于清楚被缓存的页面,同样要Buffer属性设置为true时才能使用。
6、End方法
该方法用于告诉web服务器当遇到该方法时停止处理asp.net文件。如果Response对象的Buffer属性设置为True,这时end方法即把缓存中的内容发送的客户并清楚缓冲区。所有要取消所有向客户的输出,可以先清楚缓冲区,然后使用end方法。如:
<%
Response Buffer="True" On error resume next
err.clear
if err.num<>0 then
Respone.Clear
Response.End
end if
%>
7、Flush方法
该方法将缓冲区中的所有数据送到客户段
View Code

(引用来源http://hi.baidu.com/qmzwhl/item/ffa475ff282e4a1ba729882f)

27.ASP.NET的Server对象?

Server对象提供对服务器上的方法和属性进行的访问 .其类名称是HttpServerUtility.

Server对象的主要属性有:

  MachineName:获取服务器的计算机名称。 

  ScriptTimeout:获取和设置请求超时(以秒计)。

  方法名称 说明

  CreateObject 创建 COM 对象的一个服务器实例。

  Execute 执行当前服务器上的另一个aspx页,执行完该页后再返回本页继续执行

  HtmlEncode 对要在浏览器中显示的字符串进行HTML编码并返回已编码的字符串。

  HtmlDecode 对HTML编码的字符串进行解码,并返回已解码的字符串。

  MapPath 返回与 Web 服务器上的指定虚拟路径相对应的物理文件路径。

  Transfer 终止当前页的执行,并为当前请求开始执行新页。

  UrlEncode 将代表URL的字符串进行编码,以便通过 URL 从 Web 服务器到客户端进行可靠的 HTTP 传输。

  UrlDecode 对已被编码的URL字符串进行解码,并返回已解码的字符串。

  UrlPathEncode 对 URL 字符串的路径部分进行 URL 编码,并返回已编码的字符串。

  编码:Server.HtmlEncode(“HTML代码”)

  解码:Server.HtmlDecode(“已编码的HTML”)
View Code

28.ASP.NET中七种页面跳转的方法介绍?

1、利用HTML标签,2、HyperLink控件,3、Response.Redirect()方法,4、Server.Transfer()方法,5、 Server.Execute()方法

6、Javascript实现跳转,7、Respone.Write()

29.ASP.NET有几种存储会话状态的方式?

会话状态是ASP.NET应用程序状态的其中一种,这种状态的特点是以用户为单位,每个会话对应一个用户,也就是说在该用户的整个访问过程,会话状态保存的数据都会持续保存于服务器的介质中,直到会话超时(即用户超过指定时间没有存取会话数据)。在服务器端保存会话状态的方式有几种,分别为:

1)InProc——这种方式会话状态保存在ASP.NET运行进程内,具体位置就是ASP.NET的Cache(高速缓存)内。
2)StateServer——这种方式会话状态保存在ASP.NET所带有的Wiindows服务进程中,该服务默认是禁用的,需要人手启动。
3)SQL Server——这种方式会话状态保存到SQL Server所管理的数据库中。具体又可以分为保存在临时数据库,ASPState数据库和自定义数据库三种方式。
4)自定义提供程序——这种方式要求开发人员自己开发会话状态的提供程序,会话状态的存取方式完全由该提供程序决定,由此可以保存在其他SQL数据库,或者XML文件,甚至文本文件中都可以。

原文地址:https://www.cnblogs.com/jlf19881031/p/3484105.html