详解C#装箱与拆箱--转

首先,说一下装箱和拆箱。
      在.net中的通用类型系统(Common Type system,CTS)中,所有类型都是对象(object),都派生自System.Object。CTS支持两组类型:值类型和引用类型。如果变量是值类型那么这个变量就包含实际的数据。也就是在内存中确实会分配那么一部分空间给这个变量并存储值,引用类型就类似一个类型安全的指针,本身并没有开辟内存空间去存储东西。这玩意是基础,罗嗦的重复一下。
     而装箱(box)就是将值类型转换为引用类型的过程。相反的过程就叫拆箱(unbox)。
  
     a、装箱
      一个很简单的例子。新建一个控制台程序,在Main()里面就写两句话。   
    
     int i = 13;
      object ob = i;
     编译。然后用.net 提供的工具ILDASM.exe(MSIL Disassembler )查看新生产这个程序的配件代码(Microsoft intermediate language ,MSIL。顺带说一句.net framework SDK除了这个MSIL的反汇编工具,当然还提供了汇编工具ILASM.exe,可以使用MSIL编写程序,当然。。谁也不会没事这么干。那个反汇编工具倒是挺有用,可以了解一些底层机制)
     用那个工具查看一下编译后程序的Main(string[] args)方法,显示如下(我现在用的时.net framework 2.0可能MSIL代码显示出来的和原来的1.0或者1.1稍有不同,不过没关系核心没变):
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size       12 (0xc)
.maxstack 1
.locals init ([0] int32 i,
           [1] object ob)
IL_0000: nop
IL_0001: ldc.i4.s   13
IL_0003: stloc.0
IL_0004: ldloc.0
IL_0005: box        [mscorlib]System.Int32
IL_000a: stloc.1
IL_000b: ret
} // end of method Program::Main
稍微解释一下:
(1)先注意 .locals ,定义了两个类型分别为int32 和object 的局部变量
(2)然后看   IL_0001处,ldc是个指令,后面的i4.s指出作为32位(4个字节)整数被压入堆栈。而压入的值就是13  
(3)下面的stloc把上面的值从堆栈弹出给局部变量i,这里的.0是指弹出给到第一个局部变量中,也就是i了
(4)这个值(13),被弹出后,就被装载回堆栈,也就是后面IL_0004行的ldloc命令做的事情
(5)然后使用CIL(Common Language Infrastructure )box将这个值转换为引用类型。装箱喽~
(6)stloc.1根据(3)的解释就好理解了,就是把box返回值弹出给第二个局部变量ob中。
但是这个box指令内部又发生了什么呢?有牛人告诉了我们。
   (1)在堆上分配内存。因为值类型最终有一个对象代表,所有堆上分配的内存量必须是值类型的大小加上容纳此对象及其内部结构(比如虚拟方法表)所需的内存量。
(2)值类型的值被复制到新近分配的内存中
(3)新近分配的对象地址被放到堆栈上,现在它指向一个引用类型
   b、拆箱
   在刚才程序的基础上,再加一句话变成,编译:
            int i = 13;
            object ob = i;
            int j = (int)ob;
   在装箱的时候,并不需要显示类型转换。但在拆箱时需要类型转换。这是因为在拆箱时对象可以被转换为任何类型。看看MSIL代码变成这德行了:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size       19 (0x13)
.maxstack 1
.locals init ([0] int32 i,
           [1] object ob,
           [2] int32 j)
IL_0000: nop
IL_0001: ldc.i4.s   13
IL_0003: stloc.0
IL_0004: ldloc.0
IL_0005: box        [mscorlib]System.Int32
IL_000a: stloc.1
IL_000b: ldloc.1
IL_000c: unbox.any [mscorlib]System.Int32
IL_0011: stloc.2
IL_0012: ret
} // end of method Program::Main
    整个流程就不再重复叙述了,参照前面的解释现在这个过程应该能看明白。
    说说拆箱unbox的内部过程:
   (1)因为一个对象将被转换,所以编译器必须先判断堆栈上指向合法对象的地址,以及这个对象类型是否可以转换为MSL unbox指令调用中指定的值类型。如果检查失败就抛出InvalidCastException异常。
   (2)校验通过后,就返回指向对象内的值的指针。可以看出,装箱操作会创建转换类型的副本,而拆箱就不会。不过注意一下,在我们装箱的时候是先把变量i的值复制了一份赋给ob的,所变量j拿到的是ob这个变量的引用。也就是后面再改变i的值并不会影响j的值,但是改变ob的值就会。(此处原有的的论述不正确,经过验证,改变ob的值,不会改变j的值。我认为,拆箱操作时,应该是为J在栈中又分配了一个Int32的空间,并根据指针指向的堆中的地址,也就是ob的地址,将该地址内的值全数复制到栈中,为J赋值。因此,拆箱之后,J与ob仅仅是值相等,其他再无关系)。
   c、再来一个稍微复杂点的例子,有如下代码:
            int i = 13;
            object ob = i;
            Console.WriteLine(i + "," + (Int32)ob);
    这里做了几次装箱和拆箱操作呢?我开始想当然的以为是1次装1次拆箱操作了,可实际上确是3次装箱1次拆箱操作!先看看MSIL代码:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size       45 (0x2d)
.maxstack 3
.locals init ([0] int32 i,
           [1] object ob)
IL_0000: nop
IL_0001: ldc.i4.s   13
IL_0003: stloc.0
IL_0004: ldloc.0
IL_0005: box        [mscorlib]System.Int32
IL_000a: stloc.1
IL_000b: ldloc.0
IL_000c: box        [mscorlib]System.Int32
IL_0011: ldstr      ","
IL_0016: ldloc.1
IL_0017: unbox.any [mscorlib]System.Int32
IL_001c: box        [mscorlib]System.Int32
IL_0021: call       string [mscorlib]System.String::Concat(object,
                                                              object,
                                                              object)

IL_0026: call       void [mscorlib]System.Console::WriteLine(string)
IL_002b: nop
IL_002c: ret
} // end of method Program::Main
    (1)前面好说,跟前面一样 object ob = i;引起了一次装箱操作也就是 IL_0005处代码。
    (2)后面可以看出Console.WriteLine方法调用的是单个String作为参数的版本。因此上面调用了String.Concat方法将i + "," + (Int32)ob这3个值连接产生单个String再传给WriteLine。
    (3)String.Concat的重载版本里面找到最匹配的就是Concat(object, object,object)。这样为了匹配这3个参数:
        (3.1) IL_000c处代码,第一个参数i被装箱
        (3.2)IL_0011 处ldstr      "," 就是将字符串','压入堆栈
        (3.3)然后 IL_0017 (int32)ob引起了一次拆箱操作
         (3.4)我们可怜的(int32)ob,又为了匹配Concat的参数,再次被装箱(IL_001c)
   明显后面那个(int32)ob造成了一次不必要的拆箱和装箱操作!所以正因为.net的自动类型处理能力,还是小心地注意一下写法,否则就会引起不必有的性能损失。
   下面举类似的小例子
    还是个那个控制台代码写成这样
       static ArrayList al;
        static void Main(string[] args)
        {
            int i = 13;
            al = new ArrayList();
            al.Add(i);
            Console.WriteLine("{0}", i);
           
        }
MSIL命令如下:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size       49 (0x31)
.maxstack 2
.locals init ([0] int32 i)
IL_0000: nop
IL_0001: ldc.i4.s   13
IL_0003: stloc.0
IL_0004: newobj     instance void [mscorlib]System.Collections.ArrayList::.ctor()
IL_0009: stsfld     class [mscorlib]System.Collections.ArrayList ConsoleApplication1.Program::al
IL_000e: ldsfld     class [mscorlib]System.Collections.ArrayList ConsoleApplication1.Program::al
IL_0013: ldloc.0
IL_0014: box        [mscorlib]System.Int32
IL_0019: callvirt   instance int32 [mscorlib]System.Collections.ArrayList::Add(object)
IL_001e: pop
IL_001f: ldstr      "{0}"
IL_0024: ldloc.0
IL_0025: box        [mscorlib]System.Int32
IL_002a: call       void [mscorlib]System.Console::WriteLine(string,
                                                                object)
IL_002f: nop
IL_0030: ret
} // end of method Program::Main
其他的都不用管,看懂了前面我说的,那么这里就知道因为ArrayList.Add(object)做了一次装箱和Console.WriteLine(string,object)又做了一次装箱。如果我们换一种写法,把程序改成这样:
        static ArrayList al;
        static void Main(string[] args)
        {
            int i = 13;
            object ob = i;
            al = new ArrayList();
            al.Add(ob);
            Console.WriteLine("{0}", ob);
           
        }
MSIL就变成:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size       46 (0x2e)
.maxstack 2
.locals init ([0] int32 i,
           [1] object ob)
IL_0000: nop
IL_0001: ldc.i4.s   13
IL_0003: stloc.0
IL_0004: ldloc.0
IL_0005: box        [mscorlib]System.Int32
IL_000a: stloc.1
IL_000b: newobj     instance void [mscorlib]System.Collections.ArrayList::.ctor()
IL_0010: stsfld     class [mscorlib]System.Collections.ArrayList ConsoleApplication1.Program::al
IL_0015: ldsfld     class [mscorlib]System.Collections.ArrayList ConsoleApplication1.Program::al
IL_001a: ldloc.1
IL_001b: callvirt   instance int32 [mscorlib]System.Collections.ArrayList::Add(object)
IL_0020: pop
IL_0021: ldstr      "{0}"
IL_0026: ldloc.1
IL_0027: call       void [mscorlib]System.Console::WriteLine(string,
                                                                object)
IL_002c: nop
IL_002d: ret
} // end of method Program::Main
   怎么样?就只有一次我明确指出的装箱操作了。

posted @ 2012-04-10 16:16 青蛙學堂 阅读(145) | 评论 (0)编辑 收藏

c#-装箱-拆箱


 

装箱是将值类型转换为 object 类型或由此值类型实现的任一接口类型的过程。 当 CLR 对值类型进行装箱时,会将该值包装到 System.Object 内部,再将后者存储在托管堆上。 取消装箱将从对象中提取值类型。 装箱是隐式的;取消装箱是显式的。 装箱和取消装箱的概念是类型系统 C# 统一视图的基础,其中任一类型的值都被视为一个对象。



把不同类型转换成ob类。就是装箱。拆箱是把oj类转换其他类。
如string  i=“50”;
object s=i;//装箱
int j=(int)i;//拆箱
拆箱要小心转换。但是比这个更好的有泛型

 

要掌握装箱与拆箱,就必须了解CTS及它的特点。

NET重要技术和基础之一的CTS(Common Type System)。顾名思义,CTS就是为了实现在应用程序声明和使用这些类型时必须遵循的规则而存在的通用类型系统。.Net将整个系统的类型分成两大类 ——Value Type 和 Reference Type。。,多数的OO语言存在这个弱点,原因就是因为他们的原类型没有共同的基点,于是他们在本质上并不是真正的对象C++更依赖于对象,而非面向对象。.Net环境的CTS 给我们带来了方便。第一、CTS中的所有东西都是对象;第二、所有的对象都源自一个基类——System.Object类型。这就是所谓的单根层次结构(singly rooted hierarchy)关于System.Object的详细资料请参考微软的技术文档。CTS  Value Type的一个最大的特点是它们不能为null,Value Type的变量总有一个值。在传递Value Type的变量时,实际传递的是变量的值,而非底层对象的“引用”。CTS  Reference Type就好像是类型安全的指针,它可以为null。当值为null时,说明没有引用或类型指向某个对象。声明一个引用类型的变量时,被操作的是此变量的引用(地址),而不是数据。 

    使用这种多类型系统时如何有效的拓展和提高系统的性能?就是今天探讨的问题,西雅图人提出了Box and UnBox的想法。简言之,装箱就是将value type转换为reference type;反之,就是拆箱。

装箱过程:

第一步将一个值压入堆栈;

第二步将引用类型转换为值类型;

第三步间接将值压栈;第四步传值给dubUnBox。

代码如下:

using System;
namespace Box
{
///
/// BoxAndUnBox
的摘要说明。
///
public class BoxAndUnBox
{
public BoxAndUnBox()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
/////////////////////////////////////////////////////////////////////////////////////
static void Main(string[] args)
{
double box1 =11.222; /// 定义一个值形变量
object objBox =box1; /// 将变量的值装箱到 一个引用型对象中
Console.WriteLine("The Value is '{0}' and The Boxed is {1}",box1,objBox.ToString());
}

}
}

打开ildasm.exe

MSIL代码如下:

.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
//
代码大小 42 (0x2a)
.maxstack 3
.locals init ([0] float64 box1,
              [1] object objBox)
IL_0000: nop

IL_0001: ldc.r8 11.222
IL_000a: stloc.0 //
第IL_0000至IL_000a是定义值型变量的
IL_000b: ldloc.0
IL_000c: box [mscorlib]System.Double
IL_0011: stloc.1     //
第IL_000b 至 IL_0011 行是描述object objBox =box1代码的
IL_0012: ldstr "The Value is '{0}' and The UnBoxed is {1}"
IL_0017: stloc.0
IL_0018: box [mscorlib]System.Double
IL_001d: stloc.1
IL_001e: callvirt instance string [mscorlib]System.Object::ToString()

IL_0023: call void [mscorlib]System.Console::WriteLine(string,
object,
object)

IL_0028: nop
IL_0029: ret
} // end of method BoxAndUnBox::Main

当box1被装箱时所发生的过程:

(1)划分堆栈内存,在堆栈上分配的内存 = box1的大小 + objBox及其结构所占用的空间;(2) box1的值(11.222)被复制到新近分配的堆栈中;

(3)将分配给objBox的地址压栈,此时它指向一个object类型,即引用类型。

拆箱过程:

装箱的逆过程。值得注意以下几点:box time不需要显式的类型转换,在unbox时就必须进行类型转换。因为引用类型的对象可以被转换为任何类型。电脑和人脑一个差别的体现就在于此!哈哈!类型转换不容回避的将会受到来自CTS管理中心的监控——其标准自然是依据规则。

下面这段代码:

using System;
namespace UnBox
{
///
/// BoxAndUnBox
的摘要说明。
///
public class BoxAndUnBox
{
public BoxAndUnBox()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
/////////////////////////////////////////////////////////////////////////////////////
static void Main(string[] args)
{
double box2 = 11.222;
object objBox = box2;
double dubUnBox = (double)objBox; /// 将引用型对象拆箱 ,并返回值
Console.WriteLine("The Value is '{0}' and The UnBoxed is {1}",box2,dubUnBox);
}
/////////////////////////////////////////////////////////////////////////////////////
}
}

本段代码多加了一行double dubUnBox = (double)objBox;

这段代码的含义:

第一步将一个值压入堆栈;

第二步将引用类型转换为值类型;

第三步间接将值压栈;

第四步传值给dubUnBox。

.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
//
代码大小 48 (0x30)
.maxstack 3
.locals init ([0] float64 box1,
[1] object objBox,
[2] float64 dubUnBox)
IL_0000: ldc.r8 77.769999999999996
IL_0009: stloc.0
IL_000a: ldloc.0
IL_000b: box [mscorlib]System.Double
IL_0010: stloc.1
IL_0011: ldloc.1
IL_0012: unbox [mscorlib]System.Double
IL_0017: ldind.r8
IL_0018: stloc.2
IL_0019: ldstr "The Value is '{0}' and The UnBoxed is {1}"
IL_001e: ldloc.0
IL_001f: box [mscorlib]System.Double
IL_0024: ldloc.2
IL_0025: box [mscorlib]System.Double
IL_002a: call void [mscorlib]System.Console::WriteLine(string,
object,
object)
IL_002f: ret
} // end of method BoxAndUnBox::Main

//

第IL_0011 至 IL_0018 行是描述double dubUnBox = (double)objBox代码的。

描述一下objBox在拆箱时的情况:(1)环境须先判断堆栈上指向合法对象的地址,以及在对此对象向指定的类型进行转换时是否合法,如果不合法,就抛出异常;(2)当判断类型转换正确,就返回一个指向对象内的值的指针。

改进:

为了避免由于无谓的隐式装箱所造成的性能损失,在执行这些多类型重载方法之前,最好先对值进行装箱。

代码改进:

using System;
namespace NewBU
{
///
/// BoxAndUnBox
的摘要说明。
///
public class BoxAndUnBox
{
public BoxAndUnBox()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
///////////////////////////////////////////////////////////////////
static void Main(string[] args)
{
double box1 = 11.222;
object objBox = box1;
double dubUnBox = (double)objBox;
object objUnBox = dubUnBox;
Console.WriteLine("The Value is '{0}' and The UnBoxed is {1}",objBox,objUnBox);
}
///////////////////////////////////////////////////////////////////
}
}  

 

posted @ 2012-04-10 16:07 青蛙學堂 阅读(361) | 评论 (2)编辑 收藏

C#泛型的用处--转

C#泛型的用处

昨天公司请了一个老师过来讲解QAD财务系统,可能是她声音太小,或者屏幕太过模糊导致底下很多人都昏昏欲睡,包括我。只有我的副理特别牛,一直在和那老师讨论问题,问得那老师几乎要招架不住了。我心里那个佩服啊

虽然我坐在那里没有听课,但我却不闲着,拿出我的手机打开电子书,看起.NET泛型应用的文章来。这个是以前存在手机里面的技术性文章,看过了一次,现在再拿出来看应该可以加深印象,同时还可以获得意想不到的效果吧~~~

.NET泛型在一起来最让我“害怕”,感觉它的语法很没有“规律”,怪就怪我对它的机制不太了解。

问题:

我们在编写程序时,经常遇到两个模块的功能非常相似,只是一个是处理int数据,另一个是处理string数据,或者其他自定义的数据类型,但我们没有办法,只能分别写多个方法处理每个数据类型,因为方法的参数类型不同。有没有一种办法,在方法中传入通用的数据类型,这样不就可以合并代码了吗?泛型的出现就是专门解决这个问题的。读完本篇文章,你会对泛型有更深的了解。

为什么要使用泛型

为了了解这个问题,我们先看下面的代码,代码省略了一些内容,但功能是实现一个栈,这个栈只能处理int数据类型:

public class Stack

    {

        private int[] m_item;

        public int Pop(){...}

        public void Push(int item){...}

        public Stack(int i)

        {

            this.m_item = new int[i];

        }

}

上面代码运行的很好,但是,当我们需要一个栈来保存string类型时,该怎么办呢?很多人都会想到把上面的代码复制一份,把int改成string不就行了。当然,这样做本身是没有任何问题的,但一个优秀的程序是不会这样做的,因为他想到若以后再需要longNode类型的栈该怎样做呢?还要再复制吗?优秀的程序员会想到用一个通用的数据类型object来实现这个栈:

public class Stack

    {

        private object[] m_item;

        public object Pop(){...}

        public void Push(object item){...}

        public Stack(int i)

        {

            this.m_item = new[i];

        }

    }

这个栈写的不错,他非常灵活,可以接收任何数据类型,可以说是一劳永逸。但全面地讲,也不是没有缺陷的,主要表现在:

Stack处理值类型时,会出现装箱、折箱操作,这将在托管堆上分配和回收大量的变量,若数据量大,则性能损失非常严重。

在处理引用类型时,虽然没有装箱和折箱操作,但将用到数据类型的强制转换操作,增加处理器的负担。

在数据类型的强制转换上还有更严重的问题(假设stackStack的一个实例):

Node1 x = new Node1();

            stack.Push(x);

         Node2 y = (Node2)stack.Pop();

上面的代码在编译时是完全没问题的,但由于Push了一个Node1类型的数据,但在Pop时却要求转换为Node2类型,这将出现程序运行时的类型转换异常,但却逃离了编译器的检查。

针对object类型栈的问题,我们引入泛型,他可以优雅地解决这些问题。泛型用用一个通过的数据类型T来代替object,在类实例化时指定T的类型,运行时(Runtime)自动编译为本地代码,运行效率和代码质量都有很大提高,并且保证数据类型安全。

使用泛型

下面是用泛型来重写上面的栈,用一个通用的数据类型T来作为一个占位符,等待在实例化时用一个实际的类型来代替。让我们来看看泛型的威力:

public class Stack<T>

    {

        private T[] m_item;

        public T Pop(){...}

        public void Push(T item){...}

        public Stack(int i)

        {

            this.m_item = new T[i];

        }

}

类的写法不变,只是引入了通用数据类型T就可以适用于任何数据类型,并且类型安全的。这个类的调用方法:

//实例化只能保存int类型的类

Stack<int> a = new Stack<int>(100);

      a.Push(10);

      a.Push("8888"); //这一行编译不通过,因为类a只接收int类型的数据

      int x = a.Pop();

//实例化只能保存string类型的类

Stack<string> b = new Stack<string>(100);

b.Push(10);    //这一行编译不通过,因为类b只接收string类型的数据

      b.Push("8888");

string y = b.Pop();

这个类和object实现的类有截然不同的区别:

1.       他是类型安全的。实例化了int类型的栈,就不能处理string类型的数据,其他数据类型也一样。

2.       无需装箱和折箱。这个类在实例化时,按照所传入的数据类型生成本地代码,本地代码数据类型已确定,所以无需装箱和折箱。

3.       无需类型转换。


posted @ 2012-04-10 15:51 青蛙學堂 阅读(230) | 评论 (1)编辑 收藏

PHP 开发工具集

PHP 开发工具集

这里介绍一些 PHP IDE 工具,非常见的 Editplus 之类的,都是专门为 PHP 开发的,有兴趣都可以试试看,找出自己用得顺手的就可以了,呵呵  
  我这里整理的都是专门为PHP设计的IDE,editplus,Ultra Edit等常用文本工具我就不介绍了!其中一些介绍是从那些下载站里复制过来的!
  
  Zend Studio
  开发商: http://www.zend.com/store/products/zend-studio.php
  目前公认的最强大的PHP开发工具,这种集成软件包包括了用于编辑,调试,配置PHP程序所需要的客户及服务器组件,软件包具有工业标准的PHP开发环境,代码完成引擎,功能齐全的调试器等
  
  NuSphere PHPEd
  http://www.nusphere.com/
  PhpED 通过无与伦比的PHP调试和压缩能力,以及一个新的NuSOAP web服务向导成为了PHP领域的领军产品。更加强大的Project Manager使得发布站点和应用程序比以前更加容易。现在可以在线程级别对正在运行或者开发中的程序进行测试和调校。支持 CVS 版本控制,而且,对PostgreSQL和MySQL数据库的本地支持为PHP使用开源数据库提供了一个广泛的环境。但对中文支持不太好,汉字都当作单字节处理了。PHPED还有Linux版本。
  
  PHP Coder
  http://www.phpide.de/
  PHPCoder用于快速开发和调试PHP应用程序,它很容易扩展和定制,完全能够符合开发者的个性要求.1:结合了PHP编译器和参考文档,可以对编辑中的PHP脚本进行即时预览2:支持高亮显示HTML和PHP代码;3:自动完成功能,可以自动完成用户自定义代码片断;4:标准函数提示;5:有专门的工程项目管理器;6:对象浏览器搜寻编辑中文件的包含信息,自定义函数,并以树形显示.7:支持查找对称的语句标记符;8:支持高级搜索和替换;9:自带FTP功能;10:支持运行和断点调试11:......总之,PHPCoder是一个非常实用的,功能强大的编程环境,而且它是免费的!
  
  Ankord PHP Expert Editor
  http://www.ankord.com/phpxedit.html
  PHP Expert Editor是一个容易使用的 PHP 开发工具,它的功能照顾到初级者及专业开发人员。 PHP Expert Editor 内建 http server 用作测试及除错(你也可以使用其他 http server), PHP 语法检查, FTP 功能, 程式码样板等功能。
  
  DzSoft PHP Editor
  http://www.dzsoft.com/dzphp.htm
  专为 PHP 所设计的网页程序编辑软件 - DzSoft PHP Editor,具有 PHP 编辑、侦错、浏览、原始码检视、档案浏览、可自订的原始码样本..等功能,无须架设网站主机就可以测试 PHP 指令码,是一套功能强大的 PHP 编程软件。
  DzSoft PHP Editor和Ankord PHP Expert Editor非常相识,几乎找不到他们的主要区别,关于这两个软件之间的具体内幕我也不太清楚!
  
  Dev-PHP IDE
  http://devphp.sourceforge.net/
  非常好用的php编辑器,支持php-gtk,內建許多快速html表单,非常的好用,本身含繁体语言包,另附暗地论坛的中文语言包
  
  Master PHP
  http://www.gsoftwares.com/
  一款支持PHP, PHP3, PHTML, CSS, JS, HTML, HTM and SQL的编辑器,它允许用户编辑多种一次编辑多种文件,允许插入,运行和最优化程序的脚本,用户可以通过工具栏定制按钮和窗体,可以导出html和rtf 格式,支持18种语言
  
  Komodo
  http://www.activestate.com/Products/Komodo/
  Komodo支持在Windows与Linux上,Perl、Python及JavaScript等的程序语言开发,以及多种程序语言语法不同颜色标注。这款功能强大的IDE竟然不支持中文,连中文文件名的文件都打不开!
  
  Maguma Studio
  http://www.maguma.com/
  Maguma Studio包含了编辑和调试 PHP 程序所有必须的工具。无论您是经验丰富的开发者、或是初学者它都适合您。带有十分完整的断点、分步等调试功能。支持以树形方式显示文件中的函数和类成员。
  
  PhpLens
  http://phplens.com
  PhpLens是一款专为PHP开发人员准备的快速数据库开发程序。通过使用PhpLens,可以快速的设计、发布和维护数据库驱动的网络产品。它允许你以HTML表格的形式对数据库进行浏览、编辑、创建、删除和查找。不用写任何代码,它就允许你完成上述操作。
  
  

posted @ 2012-04-08 10:54 青蛙學堂 阅读(314) | 评论 (0)编辑 收藏

Div等高问题

网站主体DIV里面有左右两个DIV.分别为TLeft和TRight
<div id="TBody">
  <div id="TLeft">
  左边的内容
  </div>
  <div id="TRight">
  右边的内容
  </div>
</div>
因为内容不同肯定左右的高度不同.背景是蓝色的,而TLeft,TRight都是白色底,高度自动100%,高度不够的会露出一大块蓝底,非常不好看.
所以我在body加载的时候设置了一下判断
    <script language="javascript" type="text/javascript">
    function SetDivHeight()
    {
       if(this.document.getElementById("TLeft").scrollHeight>this.document.getElementById("TRight").scrollHeight)
       {
           this.document.getElementById("TLeft").style.height="100%";
       }
       else
       {
           this.document.getElementById("TLeft").style.height=this.document.getElementById("TRight").scrollHeight;
       }
    }
    </script>

<body onload="SetDivHeight();">

posted @ 2012-04-03 13:55 青蛙學堂 阅读(307) | 评论 (0)编辑 收藏

c#方法参数

C#语言的方法可以使用如下四种参数(请注意和参数类型的区别):

l         值参数,不含任何修饰符。

l         引用参数,以ref修饰符声明。

l         输出参数,以out修饰符声明。

l         数组参数,以params修饰符声明。

1.  值参数

当用值参数向方法传递参数时,程序给实参的值做一份拷贝,并且将此拷贝传递给该方法,被调用的方法不会修改实参的值,所以使用值参数时,可以保证实参的值是安全的。如果参数类型是引用类型,例如是类的引用变量,则拷贝中存储的也是对象的引用,所以拷贝和实参引用同一个对象,通过这个拷贝,可以修改实参所引用的对象中的数据成员。

2.  引用参数

有时在方法中,需要修改或得到方法外部的变量值,C语言用向方法传递实参指针来达到目的,C#语言用引用参数。当用引用参数向方法传递实参时,程序将把实参的引用,即实参在内存中的地址传递给方法,方法通过实参的引用,修改或得到方法外部的变量值。引用参数以ref修饰符声明。注意在使用前,实参变量要求必须被设置初始值。

3.  输出参数

为了把方法的运算结果保存到外部变量,因此需要知道外部变量的引用(地址)。输出参数用于向方法传递外部变量引用(地址),所以输出参数也是引用参数,与引用参数的差别在于调用方法前无需对变量进行初始化。在方法返回后,传递的变量被认为经过了初始化。值参数、引用参数和输出参数的使用见下例:

using System;

class g{public int a=0;}//类定义

class Class1

{   public static void F1(ref char i)//引用参数

    {   i='b';}

    public static void F2(char i)//值参数,参数类型为值类型

    {   i='d';}

    public static void F3(out char i)//输出参数

    {   i='e';}

public static void F4(string s)//值参数,参数类型为字符串

    {   s="xyz";}

    public static void F5(g gg)//值参数,参数类型为引用类型

    {   gg.a=20;}

public static void F6(ref string s)//引用参数,参数类型为字符串

    {   s="xyz";}

    static void Main(string[] args)

    {   char a='c';

        string s1="abc";

        F2(a);//值参数,不能修改外部的a

        Console.WriteLine(a);//因a未被修改,显示c

        F1(ref a);//引用参数,函数修改外部的a的值

        Console.WriteLine(a);//a被修改为b,显示b

        Char j;

        F3(out j);//输出参数,结果输出到外部变量j

        Console.WriteLine(j);//显示e

        F4(s1);//值参数,参数类型是字符串,s1为字符串引用变量

        Console.WriteLine(s1);//显示:abc,字符串s1不被修改

        g g1=new g();

        F5(g1);//值参数,但实参是一个类引用类型变量

        Console.WriteLine(g1.a.ToString());//显示:20,修改对象数据

        F6(ref s1);//引用参数,参数类型是字符串,s1为字符串引用变量

        Console.WriteLine(s1);//显示:xyz,字符串s1被修改

    }

}

4.  数组参数

数组参数使用params说明,如果形参表中包含了数组参数,那么它必须是参数表中最后一个参数,数组参数只允许是一维数组。比如string[]和string[][]类型都可以作为数组型参数。最后,数组型参数不能再有ref和out修饰符。见下例:

using System;

class Class1

{   static void F(params int[] args)//数组参数,有params说明

    {   Console.Write("Array contains {0} elements:",args.Length);

        foreach (int i in args)

Console.Write(" {0}",i);

        Console.WriteLine();

    }

    static void Main(string[] args)

    {   int[] a = {1,2,3};

        F(a);//实参为数组类引用变量a

        F(10, 20, 30, 40);//等价于F(new int[] {60,70,80,90});

        F(new int[] {60,70,80,90});//实参为数组类引用

        F();//等价于F(new int[] {});

        F(new int[] {});//实参为数组类引用,数组无元素

    }

}

程序输出

Array contains 3 elements: 1 2 3

Array contains 4 elements: 10 20 30 40

Array contains 4 elements: 60,70,80,90

Array contains 0 elements:

Array contains 0 elements:

    方法的参数为数组时也可以不使用params,此种方法可以使用一维或多维数组,见下例:

using System;

class Class1

{   static void F(int[,] args)//值参数,参数类型为数组类引用变量,无params说明

    {   Console.Write("Array contains {0} elements:",args.Length);

        foreach (int i in args)

Console.Write(" {0}",i);

        Console.WriteLine();

    }

    static void Main(string[] args)

    {   int[,] a = {{1,2,3},{4,5,6}};

        F(a);//实参为数组类引用变量a

        //F(10, 20, 30, 40);//此格式不能使用

        F(new int[,] {{60,70},{80,90}});//实参为数组类引用

        //F();//此格式不能使用

        //F(new int[,] {});//此格式不能使用

    }

}

程序输出

Array contains 3 elements: 1 2 3 4 5 6

Array contains 4 elements: 60,70,80,90

posted @ 2012-03-18 21:02 青蛙學堂 阅读(512) | 评论 (0)编辑 收藏

c#方法和函数

都用来实现一定的功能(甚至什么也不执行);不同点在于:通常方法作为一个特定类(抽象类或实例类)的成员而存在,而函数则既可以被类包含,也可以独立于某个类。

 

如果你是c/c++背景的程序员,那以前叫函数的东西现在c#叫方法。如果c#是你的第一个语言,忘记函数吧,在c#里没有函数的概念,都叫方法

 

C#中没有函数这一概念了,都是方法
函数是独立存在的(非面向对象),可以直接调用
而方法是依存于对象的(面向对象编程),必须使用:对象.方法,来调用
如果方法在对象体中,则可以直接调用

 

构造函数是和类名相同的方法,在创建类的实例时构造这个类的方法。不用调用,自动执行的。
成员方法是你自己定义的方法。调用时用class.methodname();

 

函数和方法没有本质区别,但是通常自己写的实现特定功能的代码块叫做方法,比如你写了一个类,定义了几个方法,很少说定义了几个函数。由系统间接或直接生成的不完整代码块叫做函数,不如“事件处理函数”,却很少说“事件处理方法”

 

C#中没有行为这个概念 而事件,方法,函数则有

事件,指的是一个类有可能会引发的一个调用,任何类都可以向一个有事件的类注册这个事件的监听,那么当事件引发时,类就会受到事件通知,从而响应。

方法,指的是一个类的一些操作,比如一个Car类他有一个Move的移动方法,表示这个车子可以移动的操作(Operation)。

函数,在C#里没有太严格的定义,我的理解是静态方法都可以称之为函数,因为函数一般不和类的实例相关,而静态方法具有这个特性。函数一般代表一个子操作,他会执行一些计算或者其他纯代码性的过程,比如Math类具有很多算数学的函数,比如计算三角的函数。

 

方法和函数只是不同的语言环境下的不同说法,他们都是一样的。都可以返回值。习惯上面向对象语言中用方法一词,也有例外就是构造函数,构造函数不称为构造方法,只是习惯问题。而在面向过程的语言中一般没有方法的说法,都叫做函数。但他们实质上从语法规则上看,基本一样,也就是定义的规则相同,调用的规则相同,当然也都可以有返回值或者都可以无返回值。

 

一个函数由这么几部分组成,函数名、参数个数、参数类型、返回值,就是把函数名字去掉以后剩下的东西(返回值、参数、调用方式等)。函数在重载时,利用函数签名的不同(即参数个数与类型的不同)来区别调用者到底调用的是那个方法。

posted @ 2012-03-18 20:39 青蛙學堂 阅读(490) | 评论 (0)编辑 收藏

cookie对象


cookie 常用来对用户进行识别。


实例:
Welcome cookie
如何创建欢迎 cookie。

<%
dim numvisits
response.cookies("NumVisits").Expires=date+365 
numvisits=request.cookies("NumVisits")

if numvisits="" then
   response.cookies("NumVisits")=1
   response.write("欢迎!这是您第一次访问本页面。")
else
   response.cookies("NumVisits")=numvisits+1
   response.write("之前,您已经访问过本页面 ")
   response.write(numvisits & " 次。")
end if
%>
<html>
<body>
</body>
</html>


什么是 Cookie?
cookie 常用来对用户进行识别。cookie 是一种服务器留在用户电脑中的小文件。每当同一台电脑通过浏览器请求页面时,这台电脑也会发送 cookie。通过 ASP,您能够创建并取回 cookie 的值。
如何创建 cookie?
"Response.Cookies" 命令用于创建 cookie。
注意:Response.Cookies 命令必须位于 <html> 标签之前。
在下面的例子中,我们会创建一个名为 "firstname" 的 cookie,并向其赋值 "Alex":
<%
Response.Cookies("firstname")="Alex"
%>
向 cookie 分配属性也是可以的,比如设置 cookie 的失效时间:
<%
Response.Cookies("firstname")="Alex" 
Response.Cookies("firstname").Expires=#May 10,2020#
%>
如何取回 cookie 的值?
"Request.Cookies" 命令用于取回 cookie 的值。
在下面的例子中,我们取回了名为 "firstname" 的 cookie 的值,并把值显示到了页面上:
<%
fname=Request.Cookies("firstname")
response.write("Firstname=" & fname)
%>
输出:
Firstname=Alex
带有键的 cookie
如果一个 cookie 包含多个值的一个集合,我们就可以说 cookie 拥有键(Keys)。
在下面的例子中,我们会创建一个名为 "user" 的 cookie 集。"user" cookie 拥有包含用户信息的键:
<%
Response.Cookies("user")("firstname")="John"
Response.Cookies("user")("lastname")="Adams"
Response.Cookies("user")("country")="UK"
Response.Cookies("user")("age")="25"
%>
读取所有的 cookie
请阅读下面的代码:
<%
Response.Cookies("firstname")="Alex"
Response.Cookies("user")("firstname")="John"
Response.Cookies("user")("lastname")="Adams"
Response.Cookies("user")("country")="UK"
Response.Cookies("user")("age")="25"
%>
假设您的服务器将所有的这些 cookie 传给了某个用户。
现在,我们需要读取这些 cookie。下面的例子向您展示如何做到这一点(请注意,下面的代码会使用 HasKeys 检查 cookie 是否拥有键):
<html>
<body>

<%
dim x,y

 for each x in Request.Cookies
  response.write("<p>")
  if Request.Cookies(x).HasKeys then
    for each y in Request.Cookies(x)
      response.write(x & ":" & y & "=" & Request.Cookies(x)(y))
      response.write("<br />")
    next
  else
    Response.Write(x & "=" & Request.Cookies(x) & "<br />")
  end if
  response.write "</p>"
next
%>

</body>
</html>
输出:
firstname=Alex

user:firstname=John
user:lastname=Adams
user:country=UK
user:age=25
如何应对不支持 cookie 的浏览器?
如果您的应用程序需要和不支持 cookie 的浏览器打交道,那么您不得不使用其他的办法在您的应用程序中的页面之间传递信息。这里有两种办法:
1. 向 URL 添加参数
您可以向 URL 添加参数:
<a href="welcome.asp?fname=John&lname=Adams">
Go to Welcome Page
</a>
然后在类似于下面这个 "welcome.asp" 文件中取回这些值:
<%
fname=Request.querystring("fname")
lname=Request.querystring("lname")
response.write("<p>Hello " & fname & " " & lname & "!</p>")
response.write("<p>Welcome to my Web site!</p>")
%>
2. 使用表单
您还可以使用表单。当用户点击提交按钮时,表单会把用户输入的数据提交给 "welcome.asp" :
<form method="post" action="welcome.asp">
First Name:  <input type="text" name="fname" value="">
Last Name: <input type="text" name="lname" value="">
<input type="submit" value="Submit">
</form>
然后在 "welcome.asp" 文件中取回这些值,就像这样:
<%
fname=Request.form("fname")
lname=Request.form("lname")
response.write("<p>Hello " & fname & " " & lname & "!</p>")
response.write("<p>Welcome to my Web site!</p>")
%>

posted @ 2012-03-15 11:22 青蛙學堂 阅读(437) | 评论 (0)编辑 收藏

session对象



Session 对象用于存储关于某个用户会话(session)的信息,或者修改相关的设置。存储在 session 对象中的变量掌握着单一用户的信息,同时这些信息对于页面中的所有页面都是可用的。

Session 对象
当您正在操作一个应用程序时,您会启动它,然后做些改变,随后关闭它。这个过程很像一次对话(Session)。计算机知道你是谁。它也知道你在何时启动和关闭这个应用程序。但是在因特网上,问题出现了:web 服务器不知道你是谁,也不知道你做什么,这是由于 HTTP 地址无法留存状态(信息)。
ASP 通过为每个用户创一个唯一的 cookie 解决了这个问题。cookie 发送到服务器,它包含了可识别用户的信息。这个接口称作 Session 对象。
Session 对象用于存储关于某个用户会话(session)的信息,或者修改相关的设置。存储在 session 对象中的变量掌握着单一用户的信息,同时这些信息对于页面中的所有页面都是可用的。存储于 session 变量中的信息通常是 name、id 以及参数等。服务器会为每位新用户创建一个新的 Session 对象,并在 session 到期后撤销这个对象。
下面是 Session 对象的集合、属性、方法以及事件:
集合
集合 描述
Contents 包含所有通过脚本命令追加到 session 的条目。
StaticObjects 包含了所有使用 HTML 的 <object> 标签追加到 session 的对象。
属性
属性 描述
CodePage 规定显示动态内容时使用的字符集
LCID 设置或返回指定位置或者地区的一个整数。诸如日期、时间以及货币的内容会根据位置或者地区来显示。
SessionID 为每个用户返回一个唯一的 id。此 id 由服务器生成。
Timeout 设置或返回应用程序中的 session 对象的超时时间(分钟)。
方法
方法 描述
Abandon 撤销一个用户的 session。
Contents.Remove 从 Contents 集合删除一个项目。
Contents.RemoveAll() 从 Contents 集合删除全部项目。
事件
事件 描述
Session_OnEnd 当一个会话结束时此事件发生。
Session_OnStart 当一个会话开始时此事件发生。


1.设置并返回 LCID
本例演示 "LCID" 属性。此属性设置并返回一个指示位置或者地区的整数。类似于日期、时间以及货币等内容都要根据位置或者地区来显示。


<html>
<body>

<%  
response.write("<p>")
response.write("本页的默认 LCID 是:" & Session.LCID & "<br />")
response.write("上面的 LCID 的日期格式是:" & date() & "<br />")
response.write("上面的 LCID 的货币格式是:" & FormatCurrency(350))
response.write("</p>")

Session.LCID=1036

response.write("<p>")
response.write("现在 LCID 变更为:" & Session.LCID & "<br />")
response.write("上面的 LCID 的日期格式是:" & date() & "<br />")
response.write("上面的 LCID 的货币格式是:" & FormatCurrency(350))
response.write("</p>")

Session.LCID = 3079

response.write("<p>")
response.write("现在 LCID 变更为:" & Session.LCID & "<br />")
response.write("上面的 LCID 的日期格式是:" & date() & "<br />")
response.write("上面的 LCID 的货币格式是:" & FormatCurrency(350))
response.write("</p>")

Session.LCID = 2057

response.write("<p>")
response.write("现在 LCID 变更为:" & Session.LCID & "<br />")
response.write("上面的 LCID 的日期格式是:" & date() & "<br />")
response.write("上面的 LCID 的货币格式是:" & FormatCurrency(350))
response.write("</p>")
%>

</body>
</html>


2.返回 SessionID
本例演示 "SessionID" 属性。该属性为每位用户返回一个唯一的 id。这个 id 由服务器生成。

<html>
<body>

<%
Response.Write(Session.SessionID)
%>

</body>
</html>

3.session 的超时
本例演示 "Timeout" 属性。这个例子设置并返回 session 的超时时间(分钟)。


<html>
<body>

<%  
response.write("<p>")
response.write("默认 Timeout 是:" & Session.Timeout & " 分钟。")
response.write("</p>")

Session.Timeout=30

response.write("<p>")
response.write("现在的 Timeout 是 " & Session.Timeout & " 分钟。")
response.write("</p>")
%>

</body>
</html>



Session 何时开始?
Session 开始于:
当某个新用户请求了一个 ASP 文件,并且 Global.asa 文件引用了 Session_OnStart 子程序时;
当某个值存储在 Session 变量中时;
当某个用户请求了一个 ASP 文件,并且 Global.asa 使用 <object> 标签通过 session 的 scope 来例示某个对象时;
Session 何时结束?
假如用户没有在规定的时间内在应用程序中请求或者刷新页面,session 就会结束。默认值为 20 分钟。
如果您希望将超时的时间间隔设置得更长或更短,可以设置 Timeout 属性。
下面的例子设置了 5 分钟的超时时间间隔:
<%
Session.Timeout=5
%>
要立即结束 session,可使用 Abandon 方法:
<%
Session.Abandon
%>
注意:使用 session 时主要的问题是它们该在何时结束。我们不会知道用户最近的请求是否是最后的请求。因此我们不清楚该让 session“ 存活”多久。为某个空闲的 session 等待太久会耗尽服务器的资源。然而假如 session 被过早地删除,那么用户就不得不一遍又一遍地重新开始,这是因为服务器已经删除了所有的信息。寻找合适的超时间隔时间是很困难的。
提示:如果您正在使用 session 变量,请不要在其中存储大量的数据。
存储和取回 session 变量
Session 对象最大的优点是可在其中存储变量,以供后续的网页读取,其应用范围是很广的。
下面的例子把 "Donald Duck" 赋值给名为 username 的 session 变量,并把 "50" 赋值给名为 age 的 session 变量:
<%
Session("username")="Donald Duck"
Session("age")=50
%>
一旦值被存入 session 变量,它就能被 ASP 应用程序中的任何页面使用:
Welcome <%Response.Write(Session("username"))%>
上面这行程序返回的结果是: "Welcome Donald Duck"。
也可以在 session 对象中保存用户参数,然后通过访问这些参数来决定向用户返回什么页面。
下面的例子规定,假如用户使用低显示器分辨率,则返回纯文本版本的页面:
<%If Session("screenres")="low" Then%> 
  This is the text version of the page
<%Else%> 
  This is the multimedia version of the page
<%End If%>
移除 session 变量
contents 集合包含所有的 session 变量。
可通过 remove 方法来移除 session 变量。
在下面的例子中,假如 session 变量 "age" 的值小于 18,则移除 session 变量 "sale":
<%
If Session.Contents("age")<18 then 
  Session.Contents.Remove("sale")
End If 
%>
如需移除 session 中的所有变量,请使用 RemoveAll 方法:
<%
Session.Contents.RemoveAll()
%>
遍历 contents 集合
contents 集合包含所有的 session 变量。可通过遍历 contents 集合,来查看其中存储的变量:
<%
Session("username")="Donald Duck"
Session("age")=50

dim i
For Each i in Session.Contents
  Response.Write(i & "<br />")
Next
%>
结果:
username
age
如果需要了解 contents 集合中的项目数量,可使用 count 属性:
<%
dim i
dim j
j=Session.Contents.Count
Response.Write("Session variables: " & j)
For i=1 to j
  Response.Write(Session.Contents(i) & "<br />")
Next
%>
结果:
Session variables: 2
Donald Duck
50
遍历 StaticObjects 集合
可通过循环 StaticObjects 集合,来查看存储在 session 对象中所有对象的值:
<%
dim i
For Each i in Session.StaticObjects
  Response.Write(i & "<br />")
Next
%>


posted @ 2012-03-15 11:15 青蛙學堂 阅读(624) | 评论 (1)编辑 收藏

Request对象


Request 对象
当浏览器向服务器请求页面时,这个行为就被称为一个 request(请求)。
ASP Request 对象用于从用户那里获取信息。它的集合、属性和方法描述如下:
集合
集合 描述
ClientCertificate 包含了存储于客户证书中的域值(field values)
Cookies 包含了 HTTP 请求中发送的所有 cookie 值
Form 包含了使用 post 方法由表单发送的所有的表单(输入)值
QueryString 包含了 HTTP 查询字符串中所有的变量值
ServerVariables 包含了所有的服务器变量值
属性


QueryString 集合 实例

1.当用户点击链接时发送查询信息
本例演示如何在链接中向页面发送一些额外的查询信息,并在目标页面中取回这些信息(在本例中是同一页面)。
<html>
<body>

<a href="/example/aspe/demo_aspe_simplequerystring.asp?color=green">Example</a>

<%
Response.Write(Request.QueryString)
%>

</body>
</html>


2.对 QueryString 集合的简单应用
本例演示 QueryString 集合如何从表单取回值。此表单使用 GET 方法,
这意外着所发送的信息对用户来说是可见的(在地址中)。
GET 方法还会限制所发送信息的数量。

<html>
<body>

<form action="/example/aspe/demo_aspe_simplereqquery.asp" method="get">
First name: <input type="text" name="fname"><br />
Last name: <input type="text" name="lname"><br />
<input type="submit" value="Submit">
</form>

<%
Response.Write(Request.QueryString)
%>

</body>
</html>


3.如何使用从表单传来的信息
本例演示如何使用从表单取回的值。我们会使用 QueryString 集合。此表单使用 GET 方法。

<html>
<body>
<form action="/example/aspe/demo_aspe_reqquery.asp" method="get">
您的姓名:<input type="text" name="fname" size="20" />
<input type="submit" value="提交" />
</form>
<%
dim fname
fname=Request.QueryString("fname")
If fname<>"" Then
      Response.Write("你好!" & fname & "!<br />")
      Response.Write("今天过得怎么样?")
End If
%>
</body>
</html>


4.来自表单的更多信息
本例演示假如输入字段包含若干相同的名称的话,QueryString 会包含什么内容。它将展示如何把这些相同的名称分隔开来。它也会展示如何使用 count 关键词来对 "name" 属性进行计数。此表单使用 GET 方法。

<html>
<body>

<%
If Request.QueryString<>"" Then
      If Request.QueryString("name")<>", " Then
           name1=Request.QueryString("name")(1)
           name2=Request.QueryString("name")(2)
      end if
end if
%>

<form action="/example/aspe/demo_aspe_reqquery2.asp" method="get">
First name:
<input type="text" name="name" value="<%=name1%>" />
<br />
Last name:
<input type="text" name="name" value="<%=name2%>" />
<br />
<input type="submit" value="Submit" />
</form>
<hr>
<%
If Request.QueryString<>"" Then
      Response.Write("<p>")
      Response.Write("The information received from the form was:")
      Response.Write("</p><p>")
      Response.Write("name=" & Request.QueryString("name"))
      Response.Write("</p><p>")
      Response.Write("The name property's count is: ")
      Response.Write(Request.QueryString("name").Count)
      Response.Write("</p><p>")
      Response.Write("First name=" & name1)
      Response.Write("</p><p>")
      Response.Write("Last name=" & name2)
      Response.Write("</p>")
end if
%>
</body>
</html>


Form 集合 实例

1.一个 Form 集合的简单应用
本例演示 Form 集合如何从表单取回值。此表单使用 POST 方法,这意味着发送的信息对用户来说是不可见的,并且对所发送信息的量没有限制(可发送大量的信息)。


<html>
<body>

<form action="/example/aspe/demo_aspe_simpleform1.asp" method="post">
First name:
<input type="text" name="fname" value="Donald" />
<br />
Last name:
<input type="text" name="lname" value="Duck" />
<br />
<input type="submit" value="Submit" />
</form>

<%
Response.Write(Request.Form)
%>

</body>
</html>

2.如何使用来自表单的信息
本例演示如何使用从表单取回的信息。我们使用了 Form 集合。表单使用了 POST 方法。

<html>
<body>
<form action="/example/aspe/demo_aspe_simpleform.asp" method="post">
您的姓名:<input type="text" name="fname" size="20" />
<input type="submit" value="提交" />
</form>
<%
dim fname
fname=Request.Form("fname")
If fname<>"" Then
      Response.Write("您好!" & fname & "!<br />")
      Response.Write("今天过得怎么样?")
End If
%>
</body>
</html>


3.来自表单的更多信息
本例演示假如若干的输入域使用了相同的名称,Form 集合会包含什么信息。它将展示如何把这些相同的名称分割开来。它也会展示如何使用 count 关键词来对 "name" 属性进行计数。此表单使用 POST 方法。


<html>
<body>

<form action="/example/aspe/demo_aspe_form2.asp" method="post">
First name:
<input type="text" name="name" value="Donald" />
<br />
Last name:
<input type="text" name="name" value="Duck" />
<br />
<input type="submit" value="Submit" />
</form>
<hr />

<p>来自上面的表单的信息:</p>
<%
If Request.Form("name")<>"" Then
      Response.Write("<p>")
      Response.Write("name=" & Request.Form("name"))
      Response.Write("</p><p>")
      Response.Write("name 属性的数目:")
      Response.Write(Request.Form("name").Count)
      Response.Write("</p><p>")
      Response.Write("First name=" & Request.Form("name")(1))
      Response.Write("</p><p>") 
      Response.Write("Last name=" & Request.Form("name")(2))
      Response.Write("</p>") 
End if
%>

</body>
</html>


4.带有单选按钮的表单
本例演示如何使用 Form 集合通过单选按钮与用户进行交互。此表单使用 POST 方法。


<html>
<%
dim cars
cars=Request.Form("cars")
%>
<body>
<form action="/example/aspe/demo_aspe_radiob.asp" method="post">
<p>请选择您喜欢的汽车:</p>

<input type="radio" name="cars"
<%if cars="Volvo" then Response.Write("checked")%>
value="Volvo">Volvo</input>
<br />
<input type="radio" name="cars"
<%if cars="Saab" then Response.Write("checked")%>
value="Saab">Saab</input>
<br />
<input type="radio" name="cars"
<%if cars="BMW" then Response.Write("checked")%>
value="BMW">BMW</input>
<br /><br />
<input type="submit" value="提交" />
</form>
<%
if cars<>"" then
   Response.Write("<p>您喜欢的汽车是" & cars & "</p>")
end if
%>
</body>
</html>

5.带有复选按钮的表单
本例演示如何使用 Form 集合通过复选按钮与用户进行交互。此表单使用 POST 方法。


<html>
<body>
<%
fruits=Request.Form("fruits")
%>

<form action="/example/aspe/demo_aspe_checkboxes.asp" method="post">
<p>您喜欢哪些水果:</p>
<input type="checkbox" name="fruits" value="Apples"
<%if instr(fruits,"Apple") then Response.Write("checked")%>>
Apple
<br />
<input type="checkbox" name="fruits" value="Oranges"
<%if instr(fruits,"Oranges") then Response.Write("checked")%>>
Orange
<br />
<input type="checkbox" name="fruits" value="Bananas"
<%if instr(fruits,"Banana") then Response.Write("checked")%>>
Banana
<br />
<input type="submit" value="提交">
</form>
<%
if fruits<>"" then%>
   <p>您喜欢:<%Response.Write(fruits)%></p>
<%end if
%>

</body>
</html>


1.获取用户信息
如何查明访问者的浏览器类型、IP 地址等信息。


<html>
<body>
<p>
<b>您正在通过这款浏览器访问我们的站点:</b>
<%Response.Write(Request.ServerVariables("http_user_agent"))%>
</p>
<p>
<b>您的 IP 地址是:</b>
<%Response.Write(Request.ServerVariables("remote_addr"))%>
</p>
<p>
<b>IP 地址的 DNS 查询是:</b>
<%Response.Write(Request.ServerVariables("remote_host"))%>
</p>
<p>
<b>调用该页面所用的方法是:</b>
<%Response.Write(Request.ServerVariables("request_method"))%>
</p>
<p>
<b>服务器的域名:</b>
<%Response.Write(Request.ServerVariables("server_name"))%>
</p>
<p>
<b>服务器的端口:</b>
<%Response.Write(Request.ServerVariables("server_port"))%>
</p>
<p>
<b>服务器的软件:</b>
<%Response.Write(Request.ServerVariables("server_software"))%>
</p>

</body>
</html>

2.获取服务器变量
本例演示如何使用 ServerVariables 集合取得访问者的浏览器类型、IP 地址等信息。


<html>
<body>

<p>
所有可能的服务器变量:
</p>
<%
For Each Item in Request.ServerVariables
      Response.Write(Item & "<br />")
Next
%>

</body>
</html>

3.创建 welcome cookie
本例演示如何使用 Cookies 集合创建一个欢迎 cookie。

<%
dim numvisits
response.cookies("NumVisits").Expires=date+365 
numvisits=request.cookies("NumVisits")

if numvisits="" then
   response.cookies("NumVisits")=1
   response.write("欢迎!这是您第一次访问本页面。")
else
   response.cookies("NumVisits")=numvisits+1
   response.write("之前,您已经访问过本页面 ")
   response.write(numvisits & " 次。")
end if
%>
<html>
<body>
</body>
</html>

4.探测用户发送的字节总数
本例演示如何使用 TotalBytes 属性来取得用户在 Request 对象中发送的字节总数。

<html>
<body>

<form action="/example/aspe/demo_aspe_totalbytes.asp" method="post">
请键入一些字符:
<input type="text" name="txt"><br /><br />
<input type="submit" value="提交">
</form>

<%
If Request.Form("txt")<>"" Then
   Response.Write("您提交了:")
   Response.Write(Request.Form)
   Response.Write("<br /><br />")
   Response.Write("字节总计:")
   Response.Write(Request.Totalbytes)
End If
%>

</body>
</html>











posted @ 2012-03-15 11:02 青蛙學堂 阅读(523) | 评论 (0)编辑 收藏

仅列出标题
共43页: First 12 13 14 15 16 17 18 19 20 Last 
<2022年7月>
262728293012
3456789
10111213141516
17181920212223
24252627282930
31123456

导航

统计

常用链接

留言簿(8)

随笔分类

随笔档案

收藏夹

青蛙学堂

最新评论

阅读排行榜

评论排行榜