C#学习笔记(个人).docx
、C#基础知识1> C#中 foreach 用法foreach循环用于列举出集合中所有的元素,foreach语句中的表达式由关键字 in隔开的两个项组成。in右边的项是集合名,in左边的项是变量名,用来存放 该集合中的每个元素。该循环的运行过程如下:每一次循环时,从集合中取出一个新的元素值。放到只 读变量中去,如果括号中的整个表达式返回值为true, foreach块中的语句就能 够执行。一旦集合中的元素都已经被访问到,整个表达式的值为false,控制流 程就转入到foreach块后面 的执行语句。foreach语句经常与数组一起使用,下面实例将通过foreach语句读取数组的值 并进行显示。数组的属性:Array. Length数组的容量利用这个属性,我们可以取得数组对象允许存储的容量值,也就是数组的长度、 元素个数,这个比拟好理解,数组还有其他的属性,比方数组的维数等,属性的 用法比拟简单,学会一种,其他的格式基本一致,这里我们就不举例了。当数组的维数、容量较多时,C#提供了 foreach语句,专门用来读取集合/数组 中的所有元素,我们把这种功能叫做遍历。语法书写如下:遍历数组:foreach (type objName in collection/Array)这段语句会逐一检查数组中的所存储的变量值,并且一一将其取出,其中的type 是你所要读取的数组对象将要存储在objName变量的数据类型,而objName是定 义了一个type类型的变量名,代表每一次从集合和数组(collection/Array) 中取得的元素,coHection/Array那么是所要存取的数组对象。用这种方法只需 写一个foreach就可以遍历出除交错数组以外的所有维数的数组。例子:用foreach循环一次性遍历a数组int, a = new int2, 2, 2 1, 2 , 3, 4, 5,6, 7,8 ;/定义一个2行2列2纵深的3维数组aforeach(int i in a)Console . WriteLine文温度(K)。那么不必动系统中成百上千个Temperature属性,只需在get和set函数中 稍微修改一下代码即可:class Thermometer(private double temperature;public Thermometer (double temperature)/构造函数(this, temperature = temperature;public double Temperature(* 修改后*get return temperature-273.15; set temperature = value+273.15; *修改后* t f f f f f f f建一个控制台应用程序来测试一下,主函数为:class Test(static void Main(string args)(Thermometer a = new Thermometer (40);Console. WriteLine(a. Temperature);Console. WriteLine (首领 A0手举杯,hand); / <summary>/ </summary>public void Fall()(Console. WriteLine (首领 A 摔杯);)/ <summary> / B/ </summary>public class B/ <summary>/攻击/ </summary>public void Attack()Console. WriteLine (部下 B 发起攻击);)/ <summary>/部下c/ </summary>public class C / <summary>/ </summary>public void Attack()Console. WriteLine (部下 C 发起攻击);)电至此,三个独立的类,构造完毕。那么,怎么让部下B和C,根据首领的暗语才去相应的行动 呢?我们需要在首领A类中,采用一种方法,把其意图传递出去。在首领A类之前,分别定义一个 带形参的举杯委托RaiseEventHandler和一个不带形参的摔杯委托FallEventHandlero命名 规那么是在准备传递的方法名后加上EventHandle,不要问我为什么,介绍为什么的文章多得是, 大家大可以去查阅。本文的宗旨是,教会大家如何快速的使用委托和事件。当然,你也可以不遵 循此命名规那么,对程序的运行没有任何影响,只是会增加自己或他人日后阅读代码的难度。delegate void RaiseEventHandler(string hand);delegate void FallEventHandler();然后,在首领A类中,定义两个事件。这个类似于大家在WinForm中拖放一个Button后,双 击该Button,即可编辑其事件。/ summary/首领A举杯事件 / /summarypublic event RaiseEventHandler RaiseEvent;/ <summary> /首领A摔杯事件 / /summarypublic event FailEventHandler FallEvent;好了,做完上面两个步骤后,就可以在首领A的举杯和摔杯方法中,调用上述两个事件了。这 样,如果B和C中订阅该事件,便可自动执行了。/ summary/举杯 / /summary/ <param name二hand>手: 左、右</param> public void Raise(string hand)(Console. WriteLine (首领 A 0手举杯,hand);/调用举杯事件,传入左或右手作为参数if (RaiseEvent!=null)RaiseEvent(hand);/ <summary>/摔杯 / </summary> public void Fall()Console. WriteLine (首领 A 摔杯); /调用摔杯事件(FallEvent!=null)FallEvent ();同样,不要问为什么这样写。按照上述操作即可。一旦用熟这种方法,体会其中含义,自然就明 白为何这么写了。在部下B和C心中,必须存在首领A,才能执行A的暗示吧。所以,在B类和C类中,需要声 明一个A,该声明可以通过B和C的构造函数进行实例化。实例化之后,便可在类B和类C中 订阅类A的事件了。完整代码如下:1 class Program2 3 static void Main(string args)45 A a = new A() ; / 定义首领 A67 B b 二 new B(a) ; / 定义部下 B89 C c = new C(a) ; / 定义部下 C1011 /首领A左手举杯12 a. Raise (左);1314 /首领A右手举杯15 /a. Raise(右);1617 /首领A摔杯18 /a. Fall ();1920 Console. ReadLine();21 /由于B和C订阅了 A的事件,所以无需任何代码,B和C均会按照约定进行动作。22 23 )2425 / summary26 /首领A举杯委托27 /summary28 /<param name二hand"手:左、右</param>29 public delegate voidRaiseEventHandler(string hand);30 / summary31 /首领A摔杯委托32 / </summary>33 public delegate voidFallEventHandler();/ <summary>/首领A/ </summary>public class A/ <summary>/首领A举杯事件/ </summary>public event RaiseEventHandler RaiseEvent;/ <summary>/首领A摔杯事件/ </summary>public event FallEventHandler FallEvent;/ <summary>/举杯/ </summary>/ <param name=hand>手: 左、右/param public void Raise(string hand)Console. WriteLine(首领 A0手举杯,hand); /调用举杯事件,传入左或右手作为参数 if (RaiseEvent!=null)( RaiseEvent(hand);)/ <summary>/摔杯/ </summary>public void Fall() Console. WriteLine (首领 A 摔杯);/调用摔杯事件 if (FallEvent!=null) (FallEvent ();)/ <summary>/部下B3435363738394041424344454647484950515253545556575859606162636465666768697071727374757677/ /summary public class B78798081828384订阅举杯事件 85阅摔杯事件A a;public B(A a)this, a = a;a. RaiseEvent += new RaiseEventHandler (a_RaiseEvent) ; /a. FallEvent += new FailEventHandler (a_FallEvent); 订8687888990919293949596979899100101102103104105106107108109110111112 );113114115116117118/ / / /<summary>首领举杯时的动作</summary><param name=hand>假设首领A左手举杯,那么B攻击</param>void a_RaiseEvent(string hand)if (hand. Equals (左)Attack ();/<summary>首领摔杯时的动作</summary>void a FallEvent()Attack ();/<summary>攻击</summary>public void Attack()Console. WriteLine ("部下B发起攻击,大喊:猛人张飞来也!/<summary>部下C</summarypublic class C119120121122123124订阅举杯事件125阅摔杯事件126127128129130131132133134135136137138139140141142143144145146147148149150151虎生威);152153A a;public C(A a)/ / / /22 NULL,this, a = a;a. RaiseEvent += new RaiseEventHandler (a RaiseEvent) ; /a. FallEvent += new FailEventHandler (a_FallEvent) ; /订<summary>首领举杯时的动作</summary><param name=hand>假设首领A右手举杯,那么攻击/param>void a_RaiseEvent(string hand)if (hand. Equals (右)Attack (); )/<summary>首领摔杯时的动作</summary>void a FallEvent()Attack ();/summary 攻击</summary>public void Attack()Console. WriteLine (部下C发起攻击,一套落英神掌打得虎String.Empty三者在C#中的区别(l)NULLnull关键字是表示不引用任何对象|的空引用的文字值。null是引用类型变量的默认值。那么也 只有引用型的变量可以为NULL,如果mt i = null,的话,是不可以的,因为Int是值类型的。(2)"”和 String.Empty这两个都是表示空字符串。只不过”“理论上重新开辟内存空间,而String.Empty指向一处。 不过优化器会优化的!string.Empty不分配存储空间,”“分配一个长度为空的存储空间,所以一般用string.Empty, 为了以后跨平台,还是用string.empty。在C#中,大多数情况下nn和string.Empty可以互换使用。比方:string s =string s2 = string.Empty;if (s = string.Empty) / if 语句成立(3)判定为空字符串的几种写法,按照性能从高到低的顺序是:s.Length = 0 优于 s = string.Empty 优于 s = n"注意:1.string strl = ""和 string str2=null 的区别。strl是一个空字符串,空字符串是一个特殊的字符串,只不过这个字符串的值为空,在内存中 是有准确的指向的,string str2=null,这样定义后,只是定义了一个string类的引用,str2并没有指向任何地方, 在使用前如果不实例化的话,都将报错。23C#中params关键字应用c#params 应用params是C#开发语言中关键字,params主要的用处是在给函数传参数的时候用,就是当函数的参数 不固定的时候。在方法声明中的params关键字之后不允许任何其他参数,并且在方法声明中只允许一 个params关键字。关于参数数组,需掌握以下几点。(1)假设形参表中含一个参数数组,那么该参数数组必须位于形参列表的最后;(2)参数数组必须是一维数组;(3)不允许将params修饰符与ref和out修饰符组合起来使用;(4)与参数数组对应的实参可以是同一类型的数组名,也可以是任意多个与该数组的元素属于同一类型的 变量;(5)假设实参是数组那么按引用传递,假设实参是变量或表达式那么按值传递。(6)用法:可变的方法参数,也称数组型参数,适合于方法的参数个数不知的情况,用于传递大量的数组 集合参数;当使用数组参数时,可通过使用params关键字在形参表中指定多种方法参数,并在方法的参 数表中指定一个数组,形式为:方法修饰符返回类型方法名(params类型口 变量名)如带有参数的SQL语句,不 同的表的字段数量也不同,当你更新修改的时候就可以用。例如:params using System;public class MyClasspublic static void UseParams(params int list)for (int i = 0 ; i < list.Length; i+ + ) Console.WriteLine(listi); Console.WriteLine();)public static void UseParams2(params object list)for (int i = 0 ; i < list.Length; i+ + ) Console.WriteLine(listi); Console.WriteLine();)static void Main()UseParams(l, 2, 3);UseParams2(l, 'a', "test"); An array of objects can also be passed, as long as / the array type matches the method being called. int myarray = new int3 10,11,12;UseParams(myarray);)输出:1231atestl0111223 C#中窗体程序中的this.SuspendLayout。和this.ResumeLayout()挂起布局逻辑与恢复布局逻辑有时候,需要重新布置整个窗口里的控件的位置布局,如刚刚初始化时 就是一个例子。这样在每增加一个有dock等属性的控件时,由于这些布局都是 相对性布局,都需要重新计算位置什么的,并实际执行布局。如果一个窗口上有 50个控件,这个布局处理就要执行50次,并触发50 * n次的布局有关的事件。而实际上,在定义布局方案过程中,这些布局是没有必要每个控件定义之后就立 即执行布局的,也没有必要处理因此发出的布局事件。更合理的方法,是在全部 定义完所有控件的布局方案之后,才一次性计算布局结果,并一次执行。于是, 就设计了这两个函数。第一个函数用于暂停实际的布局,而第二个函数用于恢复 实际布局。在程序里,如果你需要大规模调整布局方案时,就可以先调用 suspendlayout,暂停布局执行,然后定义谁在前,谁在后,谁在上,谁在下, 谁填充左,谁填充右。布置完毕。resumelayout,于是,一次性处理完毕。如果注释这两个方法的调用,效果上也不会有什么变化,只是在性能上会造成 不必要的开销。一、C#基础知识(2)1.0 C#中 substring ()的用法String.SubString(int index,int length)index:开始位置,从0开始length:你要取的子字符串的长度例如:using System;using System.Collections.Generic;using System.Text;namespace str_subclass Programstatic void Main(string args)string myString = "Hello Word!"“Substring。在C#中有两个重载函数分别如下例如string subStringl = myString.Substring(O);如果传入参数为一个长整,且大于等于0,那么以这个长整的位置为起始,截取之后余下所有作为字串.如假设传入值小于0,系统会抛出ArgumentOutOfRange异常说明参数范围出界string substring2 = myString.Substring(O, 5);如果传入了两个长整参数,前一个为参数子串在原串的起始位置后一个参数为子串的长度如不合条件同样出现上述异常Console.WriteLine(subStringl);Console. WriteLine(subString2);Console. ReadLine();程序输出的结果:Hello Word!Hello拓展C#中 substr 和 substring 的区另U这两个方法比拟有意思,很像,但结果却是相差十万八千里。我也是从误用它们开始,慢慢进入 到它们的世界。因为很巧的是当start是为0的时候,二者的结果是一样,而我在这之前就看过 substr这个方法。所以让我产生一种错觉,就是只有substr,没有substring。当我发现是两 个方法来的时候,我会傻笑自己的无知。下面介绍这两个方法:substr(startLlength)表示从start位置开始取length个字符串substring(start,end)表示从start,到end之间的字符串,包括start位置的字符但是不包括 end位置的字符- I育UKdC-WCl-Vf I5A/L-AkT-TLCWCI乂V一I5A,厂、7、override 和 new 的区别override1. override是派生类用来重写基类中方法的;override不能重写非虚方法和静态方法;2. override 只能重写用 virtual> abstract、override 修饰的方法;不能使用修饰符new> static、virtual或abstract来修改override方 法。new. new是派生类用来隐藏基类中的方法的;也就是说在派生类中“看不到”基 类中的方法;1 .如果要在派生类中隐藏(不是重写)基类中的方法,而没有使用new关键字, 编译时会出现一个警告,提示如果是要隐藏基类中的方法,请使用new关键字;.派生类可以隐藏基类中的虚方法,也可以隐藏基类中的普通方法。2 .如果在派生类中用private来修饰new方法,那么只在该派生类中隐藏了基 类中的方法,在该派生类之外,相当于没有隐藏基类中的方法;.如果在派生类中隐藏了基类中的方法,在该派生类的派生类中,将延续对该 派生类对基类方法的隐藏。Js的substring和C#的Substring的作用都是从一个字符串中截取出一个子字符串,但它们 的使用方法却有很大的不同,下边我们来比拟看看:Js 的 substring语法:程序代码String.substring(start, end)说明:返回一个从start开始到end(不包含end)的子字符串。例如:程序代码var str="abcdefgh"document.write(str.substring(0,l);/return: adocument. write(str.substring(2z5);/return :cdedocument. write(str.substring(7,8);/return :hC#的 Substring语法:程序代码String.Substring(int startindex)String.Substring(int startindex, int length)说明:返回一个从startindex开始到结束的子字符串,或返回一个从startindex开始,长度为length 的子字符串。例如:程序代码string str = "abcdefgh"Response. Write(str.Substring(O,l);/return: aResponse. Write(str. Substring(2,3) ;/return:cdeResponse.Write(str.Substring(7zl);/return:hResponse. Write(str. Substring(7);/return :hResponse.Write(str.Substring( 10);/error:startindex 不能大于字符串长度。Response.Write(str.Substring(7,10);error:索引和长度必须引用该字符串内的位置。经过上边的说明对它们的使用应该有个比拟清楚的认识了,但对Js的substring还有几点要说 明:l.start不一定就是第一个参数,end也不一定就是第二个参数,substring。,1)时,开始位置 是L结束位置是3;2.当要返回的子字符串是从开始位置到结束时,end的值必须大于等于字符串的长度,如上边 的str.substring(7,8),按照索引从。开始算的话end的最大值为九但这边却用8,当然, 使用大于8的数返回的结果也是一样的,这点比拟有意思。2.0 C#中IndexOf的使用IndexOf()查找字串中指定字符或字串首次出现的位置,返首索引值,如:stLIndexOf("字“);查找''字在strl中的索引值(位置)strl.IndexOf(“字串”);查找''字串的第一个字符在strl中的索引值(位置)strl.IndexOf(,'"/start,end); 从 strl 第 start+1 个字符起,查找 end 个字符,查找''字 在字符串STR1中的位置从第一个字符算起注意:start+end不能大于strl的长度indexof参数为string,在字符串中寻找参数字符串第一次出现的位置并返回该位置。如string s=,0123dfdfdf,;int 1=5,门1纵0代"61/);这时 i =4。如果需要更强大的字符串解析功能应该用Regex类,使用正那么表达式对字符串进行匹配。indexof():在字符串中从前向后定位字符和字符串;所有的返回值都是指在字符串的绝对位 置,如为空那么为-1string test="dsdfjsdfjgkfdsdsfsgfhgjgfjgdddcT;test.indexof('d') =2从前向后定位d第一次出现的位置test.indexof(zd;l) =2从前向后 定位d从第三个字符串第一次出现的位置test.indexof(d,5,2) =6 从前向后 定位d从第5位开始查,查2位,即 从第5位到第7位;lastindexof():在字符串中从后向前定位字符和字符串;、用法和indexof()完全相同。下面介绍 IndexOfAny | |lastindexofany他们接受字符数组做为变元,其他方法同上,返回数组中任何一个字符最早出现的下标位置如下char bbv=<,s,/c7b/;string abc = "acsdfgdfgchacscdsad"Response.Write(abc.IndexOfAny(bbv) = lResponse.Write(abc.IndexOfAny(bbv, 5)=9Response.Write(abc.IndexOfAny(bbv, 5, 3)=9 lastindexofany 同上。3.0rrnt 的区别n软回车:在Windows中表示换行且回到下一行的最开始位置。相当于Mac OS里的r的效 果。在Linux、unix中只表示换行,但不会回到下一行的开始位置。r软空格:在Linux、unix中表示返回到当行的最开始位置。在Mac OS中表示换行且返回到下一行的最开始位置,相当于Windows里的n的 效果。t跳格(移至下一列)。它们在双引号或定界符表示的字符串中有效,在单引号表示的字符串中无效。rn 一般一起用,用来表示键盘上的回车键,也可只用n。 t表示键盘上的、'TAB键。就像你使用enter和shift+enter的区另如果要显示在页面上的效果还要转化为HTML 代码或用文件中的换行符号:linux,unix: rn windows : n Mac OS : r对应:n LF 或 ASCH 中的 0x0A(10)r CR 或 ASCII 中的 0x0D(13)t水平制表符-HT或ASCH中的0x09 (9)反斜杠$美圆符H双引号,单引号有关它们的来历并引起分歧垢原由:”回车(carriage return)和''换行(line feed)这两个概念的来历和区别了。 在计算机还没有出现之前,有一种叫做电传打字机(Teletype Model 33)的玩意,每秒 钟可以打10个字符。但是它有一个问题,就是打完一行换行的时候,要用去0.2秒,正好 可以打两个字符。要是在这02秒里面,又有新的字符传过来,那么这个字符将丧失。于是,研制人员想了个方法解决这个问题,就是在每行后面加两个表示结束的字符。一 个叫做''回车,告诉打字机把打印头定位在左边界;另一个叫做''换行,告诉打字机把纸向 下移一行。这就是''换行和''回车的来历,从它们的英语名字上也可以看出一二。后来,计算机创造了,这两个概念也就被般到了计算机上。那时,存储器很贵,一些科 学家认为在每行结尾加两个字符太浪费了,加一个就可以。于是,就出现了分歧。Unix系统里,每行结尾只有换行,即''n; Windows系统里面,每行结尾是、'v 换行,v回车,即、'nr; Mac系统里,每行结尾是回车一个直接后果是, Unix/Mac系统下的文件在Windows里翻开的话,所有文字会变成一行;而Windows里 的文件在Unix/Mac下翻开的话,在每行的结尾可能会多出一个八M符号。c语言编程时(windows系统)r就是return回到 本行 行首 这就会把这一行以前的输出覆盖掉如:int main() cout << "hahaha" << "r" << Hxixi"最后只显示xixi而hahaha背覆盖了n是回车+换行把光标先移到行首然后换到下一行也就是下一行的行首拉int main() cout << "hahaha" << ”rT << "xixi"那么显示:hahaha xixi4.0 C# typeof()和 GetType。区另(J总得来说他们都是为了获取某个实例具体引用的数据类型System.Typeo1、GetType。方法继承自Object,所以C#中任何对象都具有GetType()方法, x.GetType(),其中x为变量名2、typeof(x)中的x,必须是具体的类名、类型名称等,不可以是变量名称3、System.Type.GetTypeO ,有两个重载方法比方有这样一个变量i:Int32 i = new Int32();使用GetTypeO , i.GetType。返回值是Int32的类型,但是无法使用typeof(i), 因为i是一个变量,使用typeof(),那么只能:typeof(Int32),返回的同样是Int32的类型。下面我们具体来看下相关类的介绍:System.Type 类System.Type类定义了很多成员,可以用来检查某个类型的元数据,它们返回 的类型大多位于System.Reflection命名空间中。举例来说,Type.GetMethods() 返回一个Methodinfo类型的数组,Type.GetFields返回一个Fieldinfo类型的 数组等。System.Type提供的完整的成员组是很容易扩展的。使用 得到 Type 引用可以用多种方法得到一个Type类的实例。但是,由于Type是一个抽象类,所 以不能直接使用new关键字创立一个Type对象。对此我们的首选是:使用 System.Object定义的GetType()方法,它返回一个表示当前对象元数据的 Type类的实例:使用一个SportsCar实例得到类型信息SportsCar sc = new SportsCar();Type t = sc.GetType();显而易见,要想使用这个方法,必须得到类型的编译时信息(这里是SportsCar 类),并且当前在内存中类型实例。使用typeof。得到Type引用另一个取类型信息的方法是使用C# typeof操作符:使用typeof得到类型Type t = typeof(SportsCar);类似,使用typeof操作符,我们不需要建立一个实 例来提取类型信息。但是,仍然需要知道类型的编译时信息,因为typeof需要 的是类型的强类型名称,而不是文本表示。使用 。得到 Type 引用为了以更灵活的方式得到类型信息,我们可以调用System.Type类的静态成员 GetTypeO ,然后指定类型的完全限定名。采用这种方法,我们不需要得到正从 中提取元数据的类型的编译时信息,1 ) Type.GetType()方法被重载一:允许我们指定两个布尔类型的参数,一个用来控制当类型找不到时是否抛出异常, 另一个用来指示是否区分字符串大小写。例如:使用静态的Type.GetType。方法获取类型信息(如果SportsCar没有找到,那么 忽略不抛出异常信息)Type t = Type.GetType("CarLibrary.SportsCar",false,true);2 ) Type.GetType。方法被重载二:在上面的例子中,注意传入GetTypeO的字符串没有包含类型所在的程序集信息。 在这种情况下,该类型便被认为是定义在当前执行的程序集中。但是,当希望得 到一个外部私有程序集的类型元数据时,字符串参数必须使用类型完全限定名, 加上类型所在的程序集的名字(每一个都用逗号隔开):得到外部程序集中类型的类型信息Type t= Type.GetType("CarLibrary.SportsCarzCarLibrary");例如代码csharp view plain codv1. using System;using System.Reflection;2. public class Program3. publicint sampleMember;publicvoidSampleMethod() 4. staticvoidMain。5. (Type t = typeof(Program);6. 也可通过下面这种方式操作./Program obj = new Program();7. /Type t = obj.GetType();Console.WriteLine("=Methods=");8. Methodlnfo methodinfo = t.GetMethods();foreach (Me