C#编程语言
为什么要说C#呢?楼主你是不是来搞笑的?额...因为后台代码使用C#语言来实现的,既然这样咱们还是说说C#,权当了解加深记忆吧.
题目一:什么是装箱和拆箱
参考:
装箱,实质上就是将值类型转换为引用类型的过程,例如:
int i=2048;//声明一个值类型的变量
object obj=i;//对值类型变量进行装箱操作
拆箱,实质上就是将引用类型转换为值类型的过程.拆箱的过程大致可以分为两个阶段:
(1)检查对象的实例,看它是不是值类型的装箱值.
(2)把这个实例的值赋值给值类型的变量.
例如:
int i=1024;
object obj=i;//装箱
int j=(int)obj;//拆箱
说明:拆装箱会对程序性能有很大的影响.原因如下,不喜跳过,拆装箱都需要进行大量的计算.而且这些计算都是在堆上,堆的空间是有限的.
题目二:string是值类型还是引用类型
参考:说实话,不要小看C#中的这个小小的string,弄明白很不容易,咱们慢慢道来,C#中的字符串是System.String类型,该类型直接继承自System.Object,所以是引用类型,所有直接或间接继承System.ValueType的类型属于值类型,所以string是引用类型.看代码:
protected void Page_Load(object sender, EventArgs e)
{
string str1 = "这是一个字符串";
string str2 = str1;
Response.Write(object.ReferenceEquals(str1,str2)+"
");
str2 = "这是一个新的字符串";
Response.Write(object.ReferenceEquals(str1, str2) + "
");
}
注意:假设字符串是引用类型,将str1赋给str2之后,两个字符串位于同一内存地址.修改str2内容之后,str1和str2也应该位于同一内存地址.但实际的运行结构是修改str2内容之后,两个字符串位于不同的内存地址.
额...这样的执行结构可能让人误会,为什么出现这种情况?这是因为字符串对象不可修改的特性所致,字符串对象一旦被初始化后,就不能再做修改(例如插入,删除,切断等),即它是一个只读的对象.上述代码将”这是一个新的字符串”赋给str2时,实际上是初始化一个新的字符串对象并且赋给了str2引用,这就解释了上面代码的执行结果.
字符串是初始化后不能再修改的引用类型,由于字符串的特点和大量的使用,.NET提供了一种叫字符串池的机制对字符串的处理进行优化.所谓的字符串池机制就是对内存中内容相同的字符串重复使用,代码如下:
string str1=”字符串池”;
string str2=”字符串池”;
Response.Write(object.ReferenceEquals(str1, str2) + "
");
说明:上述代码中,str1和str2是分别声明的两个字符串类型的变量,由于两个字符串的值相同,所以声明str2时直接饮用str1的地址空间(而不是重新分配一块空间),即两个变量的地址相同.
问题三:简述一下StringBuilder类的作用
参考:StringBuilder类也称为可变字符串,它位于System.Text命名空间下.之所以有这个称呼,是因为该类的对象在通过追加,移除,替换或插入字符串后不会生成新的字符串对象,及字符串变量始终指向同一个对象.额...那么string的可能没有使用的必要了,别搞笑了,就算一块卫生纸也有它自己的作用,更何况是string了.
string的缺点是每次字符串变量的内容发生了改变时,都必须重新分配内存。你想想,如果创建一个迭代100000次的循环,每次迭代都将一个字符连接到字符串,这样内存中就会有100000个字符串,每个字符串仅仅与前一个字符串相伴只是有一个字符不同,性能影响是很大的。StringBuilder通过分配一个缓存,就是一个工作区来解决这些问题,在工作区中队字符串应用StringBuilder类的相关方法。包括添加,删除,移除,插入和替换字符等等。执行完之后,将调用ToString方法把工作区中的内容转换为一个字符串,方便赋给一个字符串变量。这样StringBuilder会提升一些性能。
使用string的优点呢?我随便说一个吧,使用sring的Format的方法不知道您试过没有?如果试过就一目了然了.
题目四:判断字符串为空的几种方法.
参考:在C#中,由于字符串(string)是引用类型,所以字符串的默认值是null.有时在判断一个字符串是否为空时,需要同时判断该字符串是否为null(空引用)或Enpty(空字符串””).
例如:使用null或者””判断字符串是否为空,代码如下:
string userName=null;
if(userName==null||userName==””)
{
//Code
}
也可以使用string.IsNullOrEmty方法判断字符串是否为空.使用该方法的优点是逻辑清晰且只需要一个表达式即可.
string passWord=””;
if(string.IsNullOrEmty(”passWord”))
{
//Code
}
说明:本屌一般使用这个方法.由于string.IsNullOrEmty方法在参数为null或Empty(空字符串””)时都返回true.
题目五:简述一下SB类和String类的区别
参考:这两个类都是用来处理字符串,他们有着太多的相似和关联并且可以相互转换,这叫导致包括本屌在内的很多内不区分这两者的区别,以前我只是单纯的觉得,使用SB类效率高,但是麻烦,String类正好与SB类相反.
String类表示Unicode字符的字符串,该类型的字符串对象事只读的,也就是说,一旦创建了某个字符串对象,那么该对象就不能修改.表面看来能够修改字符串的所有方法实际上并没有修改原有的字符串,而是生成另外一个全新的字符串对象.
SB类表示值为可变字符序列的类似字符串的对象.之所以说值是可变的,是因为可以对SB对象进行追加,移除,替换或插入字符等操作,这点与string恰恰相反.大多数修改SB实例的方法都返回对同一实例的引用.由于返回的是对实例的引用,因此可以调用该引用的方法或属性.如果想要编写将连续操作一次连接起来的单个语句,这将会很方便.看代码案例:
string str=”woshi”+”diaosi”
StringBuilder sb=new StringBuilder();
sb.append(“woshi”);
sb.append(“diaosi”);
分析:上面的代码分别使用string类和SB类连接字符串,但这两种方法在内存中的操作是不同的,第一种方法在内存中操作时,有3个string(分别为”woshi”,”diaosi”,”woshidiaosi”)变量;使用SB类在内存中操作时只有一个(“woshidiaosi”)变量,所以它们是完全不同的.
题目六:ArrayList和List
参考:看名字就应该知道可能关于泛型,这个要是都看不出来就不像话了.
ArrayList是一个使用起来很方便的集合类,无需进行修改即可用来存储任何引用或值类型,但是这是有代价的.添加到ArrayList中的任何引用或值类型都将隐式地向上强转为object类型.如果是值类型,则必须在将其添加到列表中时进行装箱操作,在检索时进行拆箱操作.强转以及拆装箱操作都会降低性能;在对大型集合进行循环访问时,装箱和拆箱的影响这时会异常的明显.
还有一个缺点是ArrayList缺少编译时类型检查,对于强类型语言来说,本吊感觉最大的优点就是编译时类型检查了,当然了,这也可能在某型情况是缺点;因为ArrayList会将所有项都强转为object类型,所以在编译时无法保证类型的安全.
List
问题七:你知道怎么使用非整数表示数组的索引吗?
参考:额...这个用非整数表示数组的索引有毛用?下过五子棋吗?通常使用A~E的字母表示棋盘的五列,用1~5的数组表示棋盘的五行.这个应该算是一个需求吧.如果在C#代码中表示一个棋盘,那么可能会选择一个二维数组.代码如下:
/*
* int[,] Chessboard = new int[5, 5];
* 使用上述代码中创建的数组不能按下述方式访问C3单元格
* Chessboard['C',3],要想使用非整数的数组索引器,咱们可以通过在类中
* 使用索引器实现棋盘对象
*/
public class Chessboard
{
private string[,] board;
public Chessboard()
{
board = new string[5, 5] { { "A0", "A1", "A2", "A3", "A4" }, { "B0", "B1", "B2", "B3", "B4" },
{"C0","C1","C2","C3","C4"}, {"D0","D1","D2","D3","D4"}, {"E0","E1","E2","E3","E4"} };
}
public string this[char column, int rowIdx]//索引器
{
get
{
int colIdx;
switch (column)
{
case 'A':
case 'a':
colIdx = 0;
break;
case 'B':
case 'b':
colIdx = 1;
break;
case 'C':
case 'c':
colIdx = 2;
break;
case 'D':
case 'd':
colIdx = 3;
break;
case 'E':
case 'e':
colIdx = 4;
break;
default:
throw new Exception("无效的索引");
}
return board[colIdx, rowIdx];
}
}
}
protected void Page_Load(object sender, EventArgs e)
{
Chessboard board = new Chessboard();
Response.Write(board['e',3]);
}
说明:C#中不能使用字符串表示数组的索引,如果使用字符串表示数组的索引,将出现错误.但是可以通过在类中使用索引器来实现非整数表示数组的索引.
问题八:你知道如何转换数组类型吗?
参考:在C#中主要使用Array类的ConvertAll方法来强转一位数组的类型,这个ConvertAll方法将一种类型的数组转换为另一种类型的数组.
public static TOutput[] ConvertAll
类型参数:
T:源数组元素的类型
U:目标数组元素的类型.
参数:
array:要转换为目标类型的从零开始的一维Array.
Converter:一个Converter,用于将每个元素从一种类型转换为另一种类型.
返回值:目标类型的数组,包含从源数组转换而来的元素.
说明一下:Converter是对方法的委托,它将对象转化为目标类型.array的元素被逐个地传递给Converter,转换后的元素保存在新数组中,源array保持不变.
额...BB了半天,说个例子:
protected void Page_Load(object sender, EventArgs e)
{
double[] doArray = { 15.6, 87.8, 5.6, 8.8, 1.6, 0.8 };
int[] intArray = Array.ConvertAll(doArray, new Converter(getInt));
string strDouble = "Double类型数组:\n";
string strInt = "Int类型数组:\n";
for (int i = 0; i < doArray.Length; i++)
{
strDouble+=doArray[i].ToString()+", ";
}
for (int i = 0; i < intArray.Length; i++)
{
strInt += intArray[i].ToString() + ", ";
}
Response.Write(strDouble+"
");
Response.Write(strInt+"
");
}
private int getInt(double input)
{
return (int)input;
}
可能牵扯到了委托,就是不懂这个方法又如何,实在不行咱不是用for循环转换数组嘛,条条大路通罗马.这所以要介绍这个方法是说这个方法的效率可能高一些.
问题八:如何将字符创转换为字符数组
参考:这个问题应该大家都应该知道吧,对于C#这样的高级语言,肯定包含很多方法用来解答这个问题,你看看你在看到这个问题的时候能想起几个?或者说你有几种方法?
本屌知道的就一个...System.IO下的StringReader类中的Read方法可以实现.例如:
protected void Page_Load(object sender, EventArgs e)
{
//定义字符串
string str = "今天天气好晴朗! 处处好风光!";
char[] c = new char[100];
StringReader sr = new StringReader(str);
//读取字符数组
sr.Read(c, 0, str.Length);
foreach (char item in c)
{
Response.Write(item.ToString()+"
");
}
}
下面介绍一下Read这个方法,不喜跳过.
public override int Read(char[] buffer,int index,int count)
参数buffer表示读取到的字符数组,index表示读取的起始索引,count表示要读取的字符数.
注意:该方法的返回值是读入缓冲区的总字节数.
问题九:你知道is和as这两个运算符的作用吗?
参考:楼主你是不是搞笑?这种问题就别出现在博客上了,你这纯属为了凑字数...好吧,我承认有这个嫌疑.为什么要说这两个运算符呢,那是因为本屌在做项目的用到了这么两三次,我觉得还是很有必要说说的.
is运算符
格式 : Object is objectType
返回值:is运算符用于检索对象是否与给定的类型兼容,兼容返回true,否则返回false.
案例:
strtic void Main(string []args)
{
int x=123;
if(x is int)
{
//Code
}
else
{
//Code
}
}
is运算符看名字就知道”是”的意思,比如”狗 是 动物”吗?”馒头 是 事物”吗?对象和类型的位置一目了然.
as运算符
is运算符只是用来判断的,但是as可以用来转换.as类似于强转,如果无法进行强转,则as返回null,而不时引发异常.案例:
protected void Page_Load(object sender, EventArgs e)
{
object[] objArray = new object[6];
objArray[0] = 'a';
objArray[1] = 123;
objArray[2] = "hello";
objArray[3] = true;
objArray[4] = null;
objArray[5] = 123.4;
for (int i = 0; i < objArray.Length; i++)
{
string s = objArray[i] as string;
Response.Write(i.ToString()+" : ");
if (s!=null)
{
Response.Write("'"+s+"'"+"
");
}
else
{
Response.Write("not a string"+"
");
}
}
}
as运算符相当于啥呢?”狗 转换为 动物”,”馒头 转换为 食物”,能转化就转换,不能转换返回null.
参考:大家伙坚持住,这时最后一个问题了,我保证!
在C#中,checked和unchecked关键字用于控制整型算术运算和显示转换的移除检查.checked关键字开启整型算术运算和显示转换的溢出检查.
案例:定义byte类型变量为255,当byte类型变量加1时会溢出.所以,使用checked关键字来检查是否溢出,代码如下:
byte i=255;
checked //检查是否溢出
{
i++;//自增1
}
unchecked关键字与unchecked的作用正好相反,它是取消整型算术运算和显示转换的溢出检查.
例如,顶一个整型变量并赋值,使其超出整数范围.然后,使用unchecked关键字取消对整型变量的溢出检查,代码如下:
unchecked//不检查是否溢出.
{
int i=2147483647*4;//整型变量超出整数方位,但是系统不会检查.
}
因为咱们这个是关于C#语言的一点小东西,内容的话,占据的篇幅有点多,我本想写两篇的,但是想了想,这点东西比着C#的基础知识少了不知道多少倍,大家还是应该多多的了解一下我写的这点东西(个人认为).学习的一个比较好的方法是回顾和总结.因为本屌看的书个人认为不少了,所以想停下来总结一下,加深一下记忆.因为东西大部分是本屌的小小总结.错误肯定会有,如果您发现了,请及时留言,咱们一起学习,一起进步!谢谢.