知识大全 C#基础知识回顾

Posted

篇首语:仓廪实则知礼节,衣食足则知荣辱。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 C#基础知识回顾相关的知识,希望对你有一定的参考价值。

C#基础知识回顾  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  今天在一个网站看到了一篇关于C#基础知识的文章 篇幅很长 浏览了一下 确实是基础知识 虽然顺序凌乱 没有章法 但是对于我们经常写代码的人确实应该尽量多的记住一些基础知识 掌握牢固的基础知识编程才能得心应手 最基本的东西也应该注重 因为细节决定成败

  引用类型是类型安全的指针 它们的内存是分配在堆(保存指针地址)上的

  string 数组 类 接口和委托都是引用类型

  强制类型转换与as类型转换的区别 当类型转换非法时 强制类型转换将抛出一个system invalidcastexception异常 而as不会抛出异常 它返回一个null值

  用using创建别名

  view plainprint?

  using console = nsole 访问限定符 public  该成员可以被其他任何类访问protected 该成员只能被其派生类访问private  该成员只能被本类的其他成员访问internal 该成员只能在当前编译单元的其他成员访问

  带参数列表和返回值的main方法

  view plainprint?

  class test public static int main(string[] args)

   foreach (string arg in args)

  ……

  构造函数(constructor)包括实例构造函数和静态构造函数

  构造函数与类名相同 且不能有返回值 例

  view plainprint?

  class testclass testclass()  //实例构造函数 可以访问静态成员和实例成员 用于初始化实例成员……

  

  static testclass() //静态构造函数 只能访问静态成员 用于初始化静态成员……

  类的静态成员属于类所有 不必生成实例就可以访问 它是在载入包含类的应用程序时创建的 但静态方法不能访问类的实例变量和方法 通常 静态变量是在定义时就赋初始值的

  类的实例成员属于类的实例所有 不创建实例对象就无法对其进行访问 实例成员可以访问类的静态成员和其它实例成员

  调用基类的析构函数

  view plainprint?

  class a public a()

  ……

  

  class b public b() base()  //调用基类的析构函数……

  常量 其值是在编译时设定的 必须是数值文字 默认状态下常量是静态的 例

  view plainprint?

  class a public const double pi = 常量是编译时就确定的值 只读字段是在运行才能确定的值 比如运行时才能确定的屏幕分辨率

  只读字段只能在类的析构函数中赋值

  静态只读字段

  view plainprint?

  class a public static readonly int screenwidth   //静态只读字段static a()   //静态析构函数 screenwidth =   //在静态析构函数中初始化在类的继承中 类的析构函数是不会被继承的

  一个派生类只能从一个基类继承 不能同时从多个基类继承 但可以通过继承多个接口来达到相同目的 实现多继承的唯一方法就是使用接口 例

  view plainprint?

  class myfancygrid control iserializable idatabound ……

  密封类是不能继承的类 抽象类不能被定义为密封类 且密封类的私有成员不能用protected修饰 只能用private 例

  view plainprint?

  sealed class a ……

  关键字ref和out用于指定用引用方式传递方法的参数

  它们的区别是 ref参数必须初始化 而out参数不需要初始化 所以在方法处理代码依赖参数的初始化值时使用ref 不依赖初始化值时使用out 对out参数即使在传递前对其进行了初始化 其值也不会传递到方法处理函数内部 传递时系统会将其设为未初始化 所以在方法内部必须对out参数进行初始化

  方法重载时 必须参数数目和参数类型其中之一不同 返回值不同不能作为重载

  c#不支持方法的默认值 只能通过方法重载来实现 例

  view plainprint?

  class a int method(int a)

  ……

  

  void method(int a int b) //参数数目不同    //返回值不同不能作为重载……

   view plainprint?

  params参数用于一个不定数目参数的方法 一般后面跟一个数组 例 class a public void method(params int[] i)

  ……

  方法的覆蓋 指派生类覆蓋基类的同名方法 有二种方法 )第一种是在派生类要覆蓋的方法前面加new修饰 而基类不需要作任何改动

  这种方法的缺点是不能实现多态 例

  view plainprint?

  class a public void method()  //无需任何修饰……

  

  class b a   //从基类继承 new public void method() //覆蓋基类的同名方法……

  

  class testclass a instance = new b() thod()   //这时将调用类a的method方法 而不是类b的method方法 )第二种是在派生类要覆蓋的方法前面加override修饰 而基类的同名方法前面加virtual修饰

  这样就能实现多态 例

  view plainprint?

  class a virtual public void method()   //基类定义虚方法      //虚拟方法不能定义为private 因为private成员对派生类是无法访问的……

  

  class b a     //从基类继承 override public void method()   //派生类覆蓋基类的同名虚方法……

  

  class testclass protected void test()

   a instance = new b()    //定义一个实例 类型为基类 从派生类创建//派生类总是能够向上转换为其基类thod()     //将调用派生类b的method方法 而不是基类的 这就是多态说明 new修饰的方法覆蓋不能实现多态的原因 是因为使用new时编译器只会实现早期绑定(early binding)

  即调用的方法在编译时就决定了 编译器看到thod()而instance的类是a 就会调用类a的method()方法

  override修饰的方法覆蓋可以实现多态的原因 是因为实现了后期绑定(late binding)

  使用override时强制编译器在运行时根据类的真正类型正确调用相应的方法 而不是在编译时

  而基类的同名方法必须加virtual修饰

  类的静态方法可能通过 类名 静态方法名 这种格式来调用 不能使用 实例名 静态方法名 这种方法调用

  因为类的静态方法为类所有(是属于类本身的) 而非实例所有(不是属于类的实例的)

  类的静态方法可以访问类的任何静态成员 但不能访问类的实例成员

  c#中类的变量称为字段 类的public变量称为类的公共字段

  类的属性由一个protected(也可以是private)字段和getter和setter方法构成

  view plainprint?

  class address protected string zipcode //protected字段 注意大小写public string zipcode get    //getter方法 return zipcode set    //setter方法 zipcode = value   //被传递的值自动被在这个value变量中 只读属性是指省略setter方法的属性 只读属性只能读取 不能设置

  属性也可以用限定符virtual override和abstract修饰 功能同其他类的方法

  属性有一个用处称为懒惰的初始化(lazy initialization) 即在需要类成员时才对它们进行初始化 如果类中包含了很少被引用的成员 而这些成员的初始化又会花费大量的时候和系统资源的话 懒惰的初始化就很有用了

  c#中数组对象共同的基类是system array 将数组声明为类的一个成员时 声明数组与实例化数组必须分开 这是因为只能在运行时创建了类的实例对象之后 才能实例化数组元素值

  声明

  view plainprint?

  int[] intarray   //一维数组int[ ] int array //三维数组初始化

  view plainprint?

  intarray = new int[ ] int[ ] int array = new int[ ] //声明时可以初始化遍历 )一维数组

  view plainprint?

  for (int i = i < intarray length i++) //array length返回数组所有元素的个数foreach (int i in intarray) for (int i = i < intarray getlength( ) i++) //array getlength( )返回数组第一维的个数 )多维数组

  view plainprint?

  for (int i = i < int array getlength( ) i++) //遍历三维数组for (int j = j < int array getlength( ) j++)

  for (int k = k < int array getlength( ) k++)

  ……

  数组的维数就是该数组的秩(rank) array rank可以返回数据的秩

  锯齿数组(jagged array)是元素为数组的数组 例

  view plainprint?

  int[][] jaggedarray = new int[ ][] //包含二个元素 每个元素是个数组jaggedarray[ ] = new int[ ]   //每个元素必须初始化jaggedarray[ ] = new int[ ] for (int i = i < jaggedarray length i++) //遍历锯齿数组for (int j = j < jaggedarray[i] length j++)

  ……

  类的属性称为智能字段 类的索引器称为智能数组 由于类本身作数组使用 所以用this作索引器的名称 索引器有索引参数值 例

  view plainprint?

  using system using llections

  class mylistbox protected arraylist data = new arraylist() public object this[int idx]  //this作索引器名称 idx是索引参数 get if (idx > && idx < unt)

   return data[idx] else return null set if (idx > && idx < unt)

   data[idx] = value else if (idx = unt)

   data add(value) else //抛出一个异常接口是二段不同代码之间约定 通过约定实现彼此之间的相互访问

  c#并不支持多继承 但通过接口可实现相同功能

  当在接口中指定了实现这个接口的类时 我们就称这个类 实现了该接口 或 从接口继承

  一个接口基本上就是一个抽象类 这个抽象类中除了声明c#类的其他成员类型??例如属性 事件和索引器之外 只声明了纯虚拟方法

  接口中可以包含方法 属性 索引器和事件??其中任何一种都不是在接口自身中来实现的 例

  view plainprint?

  interface iexampleinterface //property declaration int testproperty get

  //event declaration event testevevnt changed

  //mothed declaration function void testmothed()

  //indexer declaration string this[int index] get set 说明 定义接口时 在方法 属性 事件和索引器所有这些接口成员都不能用public之类的访问限定符 因为所有接口成员都是public类型的

  因为接口定义了一个约定 任何实现一个接口的类都必须定义那个接口中每一个成员 否则将编译失败 例

  view plainprint?

  using system public class fancycontrol protected string data public string data get return this data set data = value

  interface ivalidate bool validate() //接口方法

  public class mycontrol fancycontrol ivalidate public mycontrol()

   data = my control data

  public bool validate()  //实现接口 if (data == my control data )

  return true else return false

  class interfaceapp mycontrol mycontrol = new mycontrol()

  ivalidate val = (ivalidate)mycontrol   //可以将一个实现某接口的类 转换成该接口bool success = val validate()   //然后可调用该接口的方法也可以用

  view plainprint?

  bool success = mycontrol validate() 这种方法来调用validate方法 因为validate在类mycontrol中是被定义成public的 如果去除public validate方法被隐藏 就不能用这种方法调用了 这样隐藏接口方法称为名字隐藏(name hiding)

  可以用 类实例 is 接口名 来判断某个类是否实现了某接口 例 mycontrol is ivalidate  //mycontrol类的实例mycontrol是否实现了ivalidate接口当然 也可用as来作转换 根据转换结果是否为null来判断某个类是否实现了某接口 例

  view plainprint?

  ivalidate val = mycontrol as ivalidate if (null == val)

  ……  //没有实现ivalidate接口 else ……  //实现了ivalidate接口如果一个类从多个接口继承 而这些接口中如果定义的同名的方法 则实现接口的方法时 必须加接口名来区别 写成 接口名 方法名 假设test类从idatastore和iserializable二个接口继承 而这二个接口都有savedata()方法 实现savedata()方法时必须写成

  view plainprint?

  class test iserializable idatastore void iserializable savedata()

  ……

  

  void idatastore savedata()

  ……

  如果一个类从多个接口继承 为了方便可以定义一个新的接口 这个接口继续多个接口 然后类直接从这个接口继承就可以了 这个叫合并接口 例

  view plainprint?

  interface isavedata iserializable idatastore   //不需要定义任何方法或成员 只是用作合并 class test isavedata  //只要继承isavedata就可以了……

   c# 操作符优先级(从高到低)

  初级操作符 () x y f(x) a[x] x++ x—— new typeof sizeof checked unchecked一元操作符 + | ~ ++x ——x (t)x乘除操作符 * / %加减操作符 + 位移操作符 << >>关系操作符 < > <= >= is等于操作符 ==逻辑与  &逻辑异或 ^逻辑或  |条件与  &&条件或  ||条件操作符 ? 赋值操作符 = *= /= %= += = <<= >>= &= ^= |=

  所有的二元操作符除赋值符外都是左联合的 即从左到右计算

  typeof()运算符可以从一个类名得到一个system type对象 而从system object对象继承来的gettype()方法则可从一个类实例来得到一个system type对象 例

  view plainprint?

  type t = typeof(apple) //apple是一个类名apple apple = new apple() //apple是apple类的一个实例type t = apple gettype() //t 与t 是相同的通过反射得到一个类的所有成员和方法

  view plainprint?

  type t = typeof(apple) string classname = t tostring() //得到类名methodinfo[] methods = t getmethods() //得到所有方法foreach (methodinfo method in methods)

   //用method tostring()得到方法名 memberinfo[] members = t getmembers() //得到所有成员foreach (memberinfo member in members)

   //用member tostring()得到成员名 sizeof()操作符用来计算值类型变量在内存中占用的字节数(bytes) 并且它只能在unsafe(非

安全)

  代码中使用 例

  view plainprint?

  static unsafe public void showsizes()

   int i j j = sizeof(short) j = sizeof(i) 尽可能使用复合赋值操作符 它比不用复合赋值操作符的效率高

  for语句的语法为

  view plainprint?

  for (initialization boolean expression step)

  embedded statement在initialization和step部份还可以使用逗号操作符 例

  view plainprint?

  for (int i = j = i <= \xff i++ j++)

  for (int i = j = i < i += j j = i j) //输出斐波那契数列console write( i) 在switch语句中执行一个分支的代码后还想执行另一个分支的代码 可以用 goto case 分支

  操作符重载是为了让程序更加自然 容易理解 想要为一个类重新定义一个操作符 使用以下语法 public static 返回值 operator 操作符 (操作对象 [ 操作对象 ])

  说明 )所有重载的操作符方法都必须定义为public和static )从技术上说返回值可以是任何类型 但通常是返回所定义方法使用的类型 )操作对象的数目取决于重载是一元操作符还是二元操作符 一元操作符只要一个操作对象 二元操作符则需要二个

   )不管重载是一元操作符还是二元操作符 第一个操作对象的类型都必须与返回值的类型一致 而对于二元操作符的第二个操作对象的类型则可以是任何类型

   )只有下列操作符可以被重载 一元 + ! ~ ++ —— true false二元 + * / % & | ^ << >> == != > < >= <=赋值操作符(+= = * /= %=等等)无法被重载

  []和()操作符也无法被重载

   )操作符的优先级是无法改变的 运算优先级的规则是静态的

  例 假设一个invoice发票类由多个invoicedetailline类(成员只有一个double类型的amount金额属性)组成 我们重载+操作符 使之可以将invoicedetailline类的内容(注意不是金额合计)加在一起

  view plainprint?

  class invoice public arraylist detailline

  public invoice   //类的析构函数 detailline = new arraylist() //arraylist存放多个invoicedetailline类的实例

  public static invoice operator+ (invoice invoice invoice invoice ) //参数与返回值的类型一致 //invoice 与invoice 的内容合并invoice returninvoice = new invoice() foreach(invoicedetailline detailline in invoice detaillines)

  returninvoice detailline add(detailline) foreach(invoicedetailline detailline in invoice detaillines)

  returninvoice detailline add(detailline) return returninvoice

  class invoiceaddapp  //调用示例 public static void main()

   invoice i = new invoice() for(int i = i < i++)

  i detailline add(new invoicedetailline(i + ))

  invoice i = new invoice() for(int i = i < i++)

  i detailline add(new invoicedetailline(i + ))

  invoice summaryinvoice = i + i   //调用重载的操作符+方法自定义类型转换可以编写代码实际二个不同的类 结构体之间的转换

  语法 public static implicite/explicite operator 输出类型 (输入类型)

  说明 )转换方法必须是静态的

   )implicite表示隐式转换 explicite表示显式转换

   )输入类型和输出类型其中之一必须与包含转换的类或结构体类型 即转换必须与本类相关

  例

  view plainprint?

  struct celisus public float t

  public celisus(float t)

   this t = t    //this t是结构体的字段 t是参数

  public static implicite operator celisus(float t) //float=>celisus return new celisus(t)

  public static implicite operator float(celisus c) //celisus=>float return ((c t ) / Array) * 代表的(delegate)目的与c++中的函数指针相同 代表不是在编译时被定义的 而是在运行时被定义的

  代表主要有二个用途 回调(callback)和事件处理(event)

  回调通常用于异步处理和自定义处理 例

  view plainprint?

  class dbmanager static dbconnection[] activeconnections //声明回调函数public void delegate enumconnectioncallback(dbconnection connection)

  public static void enumconnections(enumconnectioncallback callback)

   foreach (dbconnection connection in activeconnections)

   callback(connection)   //执行回调函数 //调用

  view plainprint?

  class delegateapp public static void activeconncetioncallback(dbconnection connection) //处理函数……

  

  public void main()

   //创建指向具体处理函数的代表实例(新建一个代表 让它指向具体的处理函数)

  dbmanager emnuconnectioncallback mycallback = new dbmanager emnuconnectioncallback(activeconncetioncallback) dbmanager enumconnections(mycallback) //使用静态代表 上面的调用改为

  view plainprint?

  class delegateapp //创建一个指向处理函数的静态代表public static dbmanager emnuconnectioncallback mycallback = new dbmanager emnuconnectioncallback(activeconncetioncallback) public static void activeconncetioncallback(dbconnection connection)

  ……

  

  public void main()

   dbmanager enumconnections(mycallback) //在需要时才创建代表 上面的调用改为

  view plainprint?

  class delegateapp //将创建代表放在属性的getter方法中public static dbmanager emnuconnectioncallback mycallback get retun new dbmanager emnuconnectioncallback(activeconncetioncallback) public static void activeconncetioncallback(dbconnection connection)

  ……

  

  public void main()

   delegateapp app = new delegateapp() //创建应用程序dbmanager enumconnections(mycallback) 可以将多个代表整合成单个代表 例

  view plainprint?

  class positedelegateapp public static void logevent(part part)

  ……

  

  public static void emailpurchasingmgr(part part)

  ……

  

  public static void main()

   //定义二个代表inventorymanager outofstockexceptionmethod logeventcallback = new inventorymanager outofstockexceptionmethod(logevent) inventorymanager outofstockexceptionmethod emailpurchasingmgrcallback = new inventorymanager outofstockexceptionmethod(emailpurchasingmgr) //整合为一个代表 注意后加的代表先执行(这里是先执行logeventcallback)

  inventorymanager outofstockexceptionmethod onhandexceptioneventscallback = emailpurchasingmgrcallback + logeventcallback //调用代表inventorymanager mgr = new inventorymanager() mgr processinventory(onhandexceptioneventscallback) //inventorymanager类的processinventory方法的原型为 //public void processinventory(outofstockexceptionmethod exception) 可以根据需要将多个代表自由地组合成单个代表 例

  view plainprint?

  class positedelegateapp //代表指向的处理函数(三个代表三个函数)

  public static void logevent(part part)

  ……

  

  public static void emailpurchasingmgr(part part)

  ……

  

  public static void emailstoremgr(part part)

  ……

  

  public static void main()

   //通过数组定义三个代表inventorymanager outofstockexceptionmethod[] exceptionmethods = new inventorymanager outofstockexceptionmethod[ ] exceptionmethods[ ] = new inventorymanager outofstockexceptionmethod(logevent) exceptionmethods[ ] = new inventorymanager outofstockexceptionmethod(emailpurchasingmgr) exceptionmethods[ ] = new inventorymanager outofstockexceptionmethod(emailstoremgr)

  int location = //再定义一个代表(用于组合成单代表)

  inventorymanager outofstockexceptionmethod positedelegate //根据需要组合if (location = )

   positedelegate = exceptionmethods[ ] + exceptionmethods[ ] else positedelegate = exceptionmethods[ ] + exceptionmethods[ ] //调用代表inventorymanager mgr = new inventorymanager() mgr processinventory(positedelegate) c#的事件遵循 发布??预订 的设计模式 在这种模式中 一个类公布能够出现的所有事件 然后任何的类都可以预订这些事件 一旦事件产生 运行环境就负责通知每个订户事件已经发生了

  当代表作为事件的处理结果时(或者说定义具有代表的事件) 定义的代表必须指向二个参数的方法 一个参数是引发事件的对象(发布者) 另一个是事件信息对象(这个对象必须从eventargs类中派生)

  例

  view plainprint?

  using system

  class inventorychangeeventargs eventargs //事件信息对象 从eventargs类派生…… //假设定义二个public属性string sku和int change

  class inventorymanager    //事件的发布者 //声明代表public delegate void inventorychangeeventhander(object source inventorychangeeventargs e) //发布事件 event关键字可将一个代表指向多个处理函数public event inventorychangeeventhandler oninventorychangehander

  public void updateinventory(string sku int change)

   if (change == )

  return inventorychangeeventargs e = new inventorychangeeventargs(sku change) //触发事件if (oninventorychangehandler != null) //如果有预订者就触发oninventorychangehandler(this e) //执行代表指向的处理函数

  class inventorywatcher    //事件的预订者 public inventorywatcher(inventorymanager mgr) //mgr参数用于联结发布者 this inventorymanager = mgr //预订事件 用 += 调用多个处理函数mgr oninventroychangehandler += new inventorymanager inventorychangeeventhandler(oninventorychange) //事件处理函数void oninventroychange(object source inventroychangeeventargs e)

  ……

  

  inventorymanager inventorymanager

  class eventsapp     //主程序 public static void main()

   inventorymanager inventorymanager = new inventorymanager() inventorywatcher inventorywatcher = new inventorywatcher(inventorymanager)

  inventorymanager updateinventory( ) inventorymanager updateinventory( ) microsoft windows nt和ibm os/ 等操作系统都支持占先型多任务 在占先型多任务执行中 处理器负责给每个线程分配一定量的运行时间??一个时间片(timeslice) 处理器接着在不同的线程之间进行切换 执行相应的处理 在单处理器的计算机上 并不能真正实现多个线程的同时运行 除非运行在多个处理器的计算机上 操作系统调度的多线程只是根据分配给每个线程时间片进行切换执行 感觉上就像同时执行

  上下文切换(context switching)是线程运行的一部分 处理器使用一个硬件时间来判断一个指定线程的时间片何时结束 当这个硬件计时器给出中断信号时 处理器把当前运行的线程所用的所有寄存器(registers)数据存储到堆栈中 然后 处理器把堆栈里那些相同的寄存器信息存放到一种被称为 上下文结构 的数据结构中

  当处理器要切换回原来执行的线程时 它反向执行这个过程 利用与该线程相关的上下文结构 在寄存器里重新恢复与这一线程相关的信息 这样的一个完整过程称为 上下文切换

  多线程允许应用程序把任务分割为多个线程 它们彼此之间可以独立地工作 最大限度地利用了处理器时间

  view plainprint?

  using system using system threading

  class simplethreadapp public static void workerthreadmethod() //线程的执行体……      //执行一些操作

  public static void main()

   //创建一个线程代表指向线程的执行体 threadstart是创建新线程必须用到的代表threadstart worker = new threadstart(workerthreadmethod) thread t = new thread(worker)   //用线程代表创建线程t start()      //执行线程可以通过两种方式来得到一个thread对象 一种是通过创建一个新线程来得到 如上例 另一种在正在执行的线程调用静态的thread currentthread方法

  静态方法thread sleep(int ms)可以让当前线程(它自动调用thread currentthread)暂停指定毫秒的时间

  如果使用thread sleep( )那么当前线程将一直处于等待中 直到另一个线程调用这个线程的实例方法thread interrupt方法 等待才会结束

  使用thread suspend方法也能挂起线程 thread suspend方法可以被当前线程或其他线程调用 而thread sleep( )

  只能由当前线程在执行体中调用 当线程用thread suspend挂起时 必须用thread resume方法恢复 不论thread suspend方法调用了多少次 只要调用thread resume方法一次就可以线程恢复执行 用thread suspend方法并不会阻塞线程 调用立即返回 而thread sleep( )则会阻塞线程 所以确切地说thread sleep( )暂停线程 而不是挂起线程

  >  使用thread abort方法可以终止正在执行的线程 当thread abort方法被调用时 线程不会立即终止执行 运行环境将会等待 直到线程到达文档中所描述的 安全点 如果要确保线程已经完全停止 可以使用thread join方法 这是一个同步调用 同步调用意味着直到线程完全停止 调用才会返回

  thread priority属性用于设置的线程的优先级 其值是thread threadpriority枚举值 可以设为highest abovenormal normal belownormal lowest 缺省值是thread threadpriority normal

  线程的同步是为了解决多个线程同时使用同一对象产生的一些问题 通过同步 可以指定代码的临界区(critical section) 一次只有一个线程可以进入临界区

  使用system monitor类(锁定与信号量)进行线程同步

  view plainprint?

  using system using system threading

  public void savedata(string text) //线程执行函数或线程执行函数调用的对象的方法……   //执行其他一些不需要同步的处理

  monitor enter(this) //获取对象的monitor锁……   //执行需要同步的处理monitor exit(this) //释放对象的monitor锁

  ……   //执行其他一些不需要同步的处理说明 当执行monitor enter方法时 这个方法会试图获取对象上的monitor锁 如果另一个线程已经拥有了这个锁 这个方法将会阻塞(block) 直到这个锁被释放

  也可用c#的lock语句来获得和释放一个monitor锁 上面同步写成

  view plainprint?

  public void savedata(string text) //线程执行函数或线程执行函数调用的对象的方法……   //执行其他一些不需要同步的处理

  lock(this)  //获取对象的monitor锁 代码块执行完成后释放monitor锁……   //执行需要同步的处理

  ……   //执行其他一些不需要同步的处理也可以使用system threading名称空间的mutex类(互斥类)进行线程同步 与monitor锁一样 一次只有一个线程能获得一个给定的互斥 但mutex要慢得多 但它增加了灵活性 例

  view plainprint?

  using system using system threading

  class database mutex mutex = new mutex(false) //创建一个互斥 但不立即获得它//注意 创建互斥在需要同步的方法之外 实际上它只要创建一个实例public void savedata(string text) //需要同步的方法 mutex waitone()   //等待获得互斥……    //需要同步的处理mntex close()   //释放互斥 mutex类重载了三个构造函数 mutex()       //创建并使创建类立即获得互斥mutex(bool initiallyowned)    //创建时可指定是否要立即获得互斥mutex(bool initiallyowned string mutername)  //还可以指定互斥的名称

  mutex waitone方法也重载了三次 mutex waitone()      //一直等待mutex waitone(timespan time bool exitcontext)  //等待timespan指定的时间mutex waitone(int milliseconds bool exitcontext) //等待指定的毫秒

  线程的用法 )并发操作 比如一个程序监视多个口 当每个接到信息时执行一段处理时

   )复杂长时间操作 一个长时间的复杂操作可能会使界面停滞 停止用户响应 如果还允许用户停止它 或者显示进度条 显示操作执行进程信息时

  反射(reflection)就是能够在运行时查找类型信息 这是因为 net编译的可执行(pe)文件中包括msil和元数据(metadata)

  反射的中心是类system type system type是一个抽象类 代表公用类型系统(mon type system cts)中的一种类型

  view plainprint?

  using system using system reflection //反射命名空间 必须引用

  public static void main(string[] args)

   int i = type t = i gettype()    //根据实例得到类型t = type gettype( system int ) //根据类型的字符名称得到类型通过assembly类可以得到已经编译 net framework程序的中所有类型 例

  view plainprint?

  using system using system diagnostics   //为了使用process类using system reflection   //为了使用assembly类

  class gettypesapp protected static string getassemblyname(string[] args)

   string assemblyname if ( == args length) //如果参数为空 取当前进程的名称 process p = process getcurrentprocess() assemblyname = p processname + exe else assemblyname = args[ ] //取第一个参数 即当前运行程序名

  return assemblyname

  public static void main(string[] args)

   string assemblyname = getassemblyname(args) assembly a = assembly loadfrom(assemblyname) //调用编译程序集type[] types = a gettypes()    //得到多个类型foreach (type t in types)    //遍历类型数组……  //取得t fullname t basetype fullname等类型信息一个应用程序可以包括多个代码模块 若要将一个cs文件编译一个模块 只要执行下面的命令 csc /target module 要编译的模块 cs  //csc是c sharp piler(c#编译器)

  然后在应用程序中using编译的模块 cs中的namespace即可应用了

  要反射应用程序中所有代码模块(module) 只要 view plainprint?

  assembly a = assembly loadfrom(assemblyname) //应用程序的物理文件名module[] modules = a getmodules() foreach(module m in modules)

  …… //显示m name等后期绑定(latebinding) 例

  view plainprint?

  string[] filenames = directory getfiles(environment currentdirectory * dll ) foreach (string filename in filenames)

   assembly a = assembly loadfrom(filename) type[] types = a gettypes() foreach(type t in types)

   if (t issubclassof(typeof(mprotocol)))  //判断是否有mprotocol的派生类 object o = activator createinstance(t)   //生成实例methodinfo mi = t getmethod( displayname ) mi invoke(o null)     //调用方法 //带参数的例子

  view plainprint?

  namespace programming_csharp using system using system reflection

  public class tester public static void main( )

   type t = type gettype( system math ) object o = activator createinstance(t)

  // 定义参数类型type[] paramtypes = new type[ ] paramtypes[ ]= type gettype( system double )

  methodinfo cosineinfo = t getmethod( cos paramtypes)

  //设置参数数据object[] parameters = new object[ ] parameters[ ] =

  //执行方法object returnval = cosineinfo invoke(o parameters) console writeline( the cosine of a degree angle returnval) 动态生成代码和动态调用的完整例子 //动态生成代码的部分view plainprint?

  using system using system reflection using system reflection emit   //动态生成代码必须引用

  namespace ilgenserver public class codegenerator public codegenerator()

   currentdomain = appdomain currentdomain   //得到当前域assemblyname = new assemblyname()   //从域创建一个程序集assemblyname name = tempassembly //得到一个动态编译生成器 assemblybuileraccess run表示只在内存中运行 不能保存assemblybuilder = currentdomain definedynamicassembly(assemblyname assemblybuileraccess run) //从编译生成器得到一个模块生成器modulebuilder = assemblybuilder definedynamicmodule( tempmodule ) //模块生成器得到类生成器typebuilder = modulebuilder definetype( tempclass typeattributes public) //为类添加一个方法methodbuilder = typebuilder definemethod( helloword methodattributes public null null) //为方法写入代码 生成代码必须使用到il生成器msil = methodbuilder getilgenerator() msil emiriteline( hello world ) msil emit(opcodes ret) //最后还需要编译(build)一下类t = typebuilder createtype()

  appdomain currentdomain assemblyname assemblyname assemblybuilder assemblybuilder modulebuilder modulebuilder typebuilder typebuilder methodbuilder methodbuilder ilgenerator msil object o type t public type t get return this t //动态调用的部分

  view plainprint?

  using system using system reflection using ilgenserver   //引用动态生成代码的类

  public class ilgenclientapp public static void main( codegenerator gen = new codegenerator() //创建动态生成类type t = gen t if (null != t)

   object o = activator createinstance(t) methodinfo helloworld = t getmethod( helloworld ) //为调用方法创建一个methodinfo if (null != helloworld)

   helloworld invoke(o null)   //调用方法调用dll

  view plainprint?

  using system using system runtime interopservices //为了使用dllimport特性

  class pinvokeapp [dllimport( user dll charset=charset ansi)] //charset ansi指定ansi版本的函数(messageboxa) charset unicode指定unicode版本的函数(messageboxw)

  static extern int messagebox(int hwnd string msg string caption int type)   //声明dll中的函数

  //[dllimport( user dll entrypoint= messageboxa )] //用这种方法使用不同的函数名//static extern int msgbox(int hwnd string msg string caption int type)

  //[dllimport( user dll charset=charset unicode)]  //调用unicode版的dll函数//static extern int messagebox(int hwnd [marshalas(unmanagedtype lpwstr)]string msg // [marshalas(unmanagedtype lpwstr)]string caption int type) //将lpwstr翻译为string型 缺省情况系统只将lpstr翻译成string public static void main()

   messagebox( hello world! captionstring )   //调用dll中的函数例 使用回调

  view plainprint?

  class callbackapp [dllimport( user dll )] static extern int geindowtext(int hwnd stringbuilder text int count)

  delegate bool callbackdef(int hwnd int lparam)

  [dllimport( user dll )] static extern int enumwindows(callbackdef callback int lparam)

  static bool prinindow(int hwnd int lparam)

   stringbuilder text = new stringbuilder( ) geindowtext(hwnd text ) console writeline( window caption text) return true

  static void main()

   callbackdef callback = new callbackdef(prinindow) enumwindows(callback ) 关键字unsafe指定标记块在非控环境中运行 该关键字可以用于所有的方法 包括构造函数和属性 甚至还有方法中的代码块 关键字fixed负责受控对象的固定(pinning) pinning是一种动作 向垃圾收集器(garbage collector gc)指定一些不能被移动的对象 为了不在内存中产生碎片 net运行环境把对象四处移动 以便于最有效地利用内存 使用fixed后指定对象将不会被移动 所以就可以用指针来访问它

  c#中只能得到值类型 数组和字符串的指针 在数组的情况下 第一个元素必须是值类型 因为c#实际上是返回一个指向数组第一个元素的指针 而不是返回数组自身

  & 取一个变量的内存地址(即指向该变量的指针)

  * 取指针所指变量的值 > 取成员例

  view plainprint?

  using system

  class unsafeapp public static unsafe void getvalues(int* x int* y)

   *x = *y =

  public static unsafe void main()

   int a = int b = getvalues(&a &b) fixed语法为 fixed(type* ptr = expression) statements其中type也可以为非控类型 也可是void expression是任何产生一个type指针的表达式 statements是应用的代码块 例

  view plainprint?

  fixed (int* f = &foo x)  //foo是foo类的一个实例 x是foo类的一个int属性 setfoovalue(f)   //setfoovalue方法的定义为unsafe static void setfoovalue(int* x)

  传统的组件可以通过互操作层( interop)与 net运行环境交互 互操作层处理在托管运行环境和非托管区域中的组件操作之间传递所有的消息

  要使组件能在 net环境中使用 必须为组件生成元数据 net运行环境用元数据层业判断类型信息 在运行时刻使用类型信息 以便生成rcw(runtime callable wrapper 运行时可调用包装) 当 net应用程序与对象交互时 rcw处理对对象的装载和调用 rcw还完成许多其他的工作 如管理对象标识 对象生存周期以及接口缓冲区

  对象生存周期管理十分关键 因为 net gc把对象到处移动 并且当对象不再使用时 自动处理这些对象 rcw服务告诉 net 应用程序正与托管 net组件交互 同时又使非托管组件 觉得 对象是被传统的客户端调用的

cha138/Article/program/net/201311/12010

相关参考

知识大全 基于PHP中的常用函数回顾

基于PHP中的常用函数回顾  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!以下是对PHP中的常用函数

知识大全 回顾改革开放30年历程,启示和感想 800字

回顾改革开放30年历程,启示和感想800字,写一篇"回顾改革开放30周年来的感想"不低于800字.改革开放三十年的感想从1978年的十一届三中全会到今天2008年即将到来的奥运会,中国的改革开放已经经

知识大全 .Net-Java 争论的再次回顾

.Net-Java争论的再次回顾  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  对于许多金融机构

知识大全 语文课堂六下答案。人教版 (回顾拓展三)

语文课堂六下答案。人教版(回顾拓展三)1、遭殃央求秧苗枯萎委员萎缩绸缎片段锻炼三番五次翻来覆去2.枯萎插秧锻炼一番勃勃生机狂风暴雨3、莫名其妙无缘无故语重心长依赖4.高大的树奉献的心懒惰的人百年的基业

知识大全 2008主流数据库产品回顾与展望

  年终于离去这一年中国承受了太多的灾难然而在天灾之后我们又不得不面对来势汹汹的经济危机这样的一个虽然灰暗但是却让人难以忘怀在期待美好的新的一年时还是让我们一起来回顾一下年数据库市场以及相关领域的风云

知识大全 从个人主页到企业级开发 PHP发展回顾

从个人主页到企业级开发PHP发展回顾  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  当Rasmu

知识大全 对等(P2P)计算实际使用之发展历史回顾

对等(P2P)计算实际使用之发展历史回顾  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  对等网络

知识大全 小学六年级语文作业本回顾拓展五第五题答案

小学六年级语文作业本回顾拓展五第五题答案虽然有的题目比较费时间,但是也只能这样来提高自己的学习水平,多和老师交流,在网上是问不到答案的哈老师是很乐意学生去问问题的,问多了老师也会给很多学习上的建议六年

知识大全 人教版五年级上册语文课堂作业本回顾·拓展七第6题

人教版五年级上册语文课堂作业本回顾·拓展七第6题?急!序号是(6)(5)(2)(4)(1)(3)第二题:炊事员老李知道无论怎么劝说赵一曼都不会吃这碗高粱米饭,所以也没有吭声,因为他被赵一曼处处为他人着

知识大全 请你回顾学过的古诗词,写出两句含雁的诗句,要注明诗人和出处

请你回顾学过的古诗词,写出两句含雁的诗句,要注明诗人和出处雁过也,正伤心,却是旧时相识(李清照《声声慢》)千里黄云白日曛,北风吹雁雪纷纷(高适《别董大其二》)请你写出两句含“燕”字的诗句,并注明出处。