日期:
2008-6-8
学习内容:泛型,装箱和拆箱,
C#
中的数据类型,
C#
中的字符
遗留问题:
学习总结:
1.
泛型的引入
using
System;
namespace
ConsoleApplication3
{
class Stack
{
private int[] items;//
定义一个数组用于存储在栈中的值
private int count;//
定义一个变量存储栈中元素的个数
public Stack(int size)//
带参数的构造函数,初始化栈
{
items = new int[size];//
给数组元素指定大小
count = 0;
}
public void Push(int x)//
成员方法,入栈
{
items[count++] = x;
}
public int Pop()//
成员方法,出栈
{
return items[--count];
}
}
class Test
{
static void Main (string[] args)
{
Stack s = new Stack(10);//
声明一个Stack类的实例,栈的大小为10个元素
s.Push(111);//
调用Push方法将数据压入栈中
s.Push(222);
Console.WriteLine(s.Pop()+s.Pop());//
调用Pop方法,是栈中的元素出栈,并使出栈的元素相加
}
}
}
如果用户的需求发生改变了,既想输入整数的值又想输入其他类型的数值该怎么办呢?第一种方法:继续重载第二种方法:引用object类 第三种方法:泛型
第二中方法的例子:
using
System;
namespace
ConsoleApplication3
{
class Stack
{
private object[] items;//
定义一个数组用于存储在栈中的值
private int count;//
定义一个变量存储栈中元素的个数
public Stack(int size)//
带参数的构造函数,初始化栈
{
items = new object[size];//
给数组元素指定大小
count = 0;
}
public void Push(object x)//
成员方法,入栈
{
items[count++] = x;
}
public object Pop()//
成员方法,出栈
{
return items[--count];
}
}
class Test
{
static void Main (string[] args)
{
Stack s = new Stack(10);//
声明一个Stack类的实例,栈的大小为10个元素
s.Push(123);//
调用Push方法将数据压入栈中
s.Push(456);
Console.WriteLine((int)s.Pop() +(int)s.Pop());//
调用Pop方法,是栈中的元素出栈,并使出栈的元素相加
}
}
}
问题:如果用户先输入一个整型数,再输入一个浮点型的数,编译能通过,但运行时出现system.invalicastexcption异常,隐藏的缺陷,不容易发现错误。且在程序中出现了大量的装箱和拆箱操作,程序的性能下降
第三种方法的例子:
using
System;
namespace
ConsoleApplication3
{
class Stack<T>
{
private T[] items;//
定义一个数组用于存储在栈中的值
private int count;//
定义一个变量存储栈中元素的个数
public Stack(int size)//
带参数的构造函数,初始化栈
{
items = new T[size];//
给数组元素指定大小
count = 0;
}
public void Push(T x)//
成员方法,入栈
{
items[count++] = x;
}
public T Pop()//
成员方法,出栈
{
return items[--count];
}
}
class Test
{
static void Main (string[] args)
{
Stack<string> s = new Stack<string>(10);//
声明一个Stack类的实例,栈的大小为10个元素
s.Push("123");//
调用Push方法将数据压入栈中
s.Push("445");
Console.WriteLine(s.Pop() +s.Pop());//
调用Pop方法,是栈中的元素出栈,并使出栈的元素相加
}
}
}
泛型的引用:大大减少了装箱和拆箱的操作,提高了程序的性能
查看是否进行了装箱和拆箱操作的方法:打开
MIL
反汇编程序,打开编译后生成的
.exe
文件,即可查看
2.
装箱和拆箱
只有被装了箱的值类型,才能进行拆箱操作
3.
C#
中的数据类型
在
C#
中有两种类型:值类型和引用类型。值类型的变量直接包含它们中的数据,而引用类型的变量存储的是对它们数据的引用(即指向对象的指针),后者称为对象。
上图展示了
C#
中类型的组织结构
,object
类是各种类型的基类
引用类型在内存的托管堆中(包括同步块和方法表),值类型的对象分配在内存的堆栈中
using
System;
namespace
ConsoleApplication4
{
class Myclass
{
public int i;
}
class Test
{
static void Main (string[] args)
{
Myclass mc = new Myclass();
mc.i = 100;
Myclass mc1 = mc;
mc1.i = 200;
Console.WriteLine("mc.i="+mc.i);
Console.WriteLine("mc1.i="+mc1.i);
}
}
}
//
输出结果mc.i=200,mc1.i=200
注意:mc和mc1指向的是同一块托管堆
using
System;
namespace
ConsoleApplication4
{
struct Myclass
{
public int i;
}
class Test
{
static void Main (string[] args)
{
Myclass mc = new Myclass();
mc.i = 100;
Myclass mc1 = mc;//
拷贝的是mc的副本
mc1.i = 200;
Console.WriteLine("mc.i="+mc.i);
Console.WriteLine("mc1.i="+mc1.i);
}
}
}
//
输出结果mc.i=100,mc1.i=200
注意:值类型各有个的块
using
System;
namespace
ConsoleApplication4
{
class Myclass
{
public int i;
}
class Test
{
static void Seti(Myclass m)
{
m.i = 300;
}
static void Main (string[] args)
{
Myclass mc = new Myclass();
mc.i = 100;//
在托管堆中分配存储空间存储100的值,在堆栈中存储的是指向100的地址
Myclass mc1 = mc;//
将mc中的地址赋给mc1,让他也指向100
Seti(mc1);//
调用构造方法,让对象m也指向100,并修改他的值为300
Console.WriteLine("mc.i="+mc.i);
Console.WriteLine("mc1.i="+mc1.i);
}
}
}
//
输出的结果为:mc.i=300,mc1.i=300
using
System;
namespace
ConsoleApplication4
{
struct Myclass
{
public int i;
}
class Test
{
static void Seti(Myclass m)
{
m.i = 300;
}
static void Main (string[] args)
{
Myclass mc = new Myclass();
mc.i = 100;//
在堆栈中存储100的值
Myclass mc1 = mc;//
创建100的副本给mc1
Seti(mc1);//
创建100的副本给m,修改的是m中的i值
Console.WriteLine("mc.i="+mc.i);
Console.WriteLine("mc1.i="+mc1.i);
}
}
}
//
输出的结果为:mc.i=100,mc1.i=100
值类型的使用场合:
当类型是一个十分简单的类型,其中没有成员会修改类型的任何实例字段
类型不需要从任何其他类型继承
类型不会派生出任何其他类型
类型的实例较小
类型不作为方法参数传递,也不作为方法的返回类型使用
4.
C#
中的字符
在
.net framework
中,字符总表示成
16
位的
Unicode
代码值,这简化了全球引用程序的开发。一个字符表示成
System.char
结构(一个值类型)的一个实例
using
System;
using
System.Collections.Generic;
using
System.ComponentModel;
using
System.Data;
using
System.Drawing;
using
System.Text;
using
System.Windows.Forms;
namespace
WindowsApplication2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string s;
s = textBox1.Text;
foreach (char c in s)
{
int i = (int)c;//
将汉字强制转换为整型
if (i < 0x4e00 || i > 0x9fa5)//
汉字的十六进制的取值范围为0x9fa5-0x4e00
MessageBox.Show("
用户名输入有误!"
);
}
}
}
}