一、C#是强类型的语言,即每个对象有且只有一种类型。这个类型在对象创建时就已经完成定义,并在对象执行期间保持不变,C#的所有变量在使用之前都必须完成初始化。

二、托管线程栈

1)        每个windows线程都有一个私有的内存区域,称为栈。线程的栈的作用在于

                        i.              保存正在执行中的方法的传入实参值;

                      ii.              保存方法返回时需要跳转的本地代码的地址;

                    iii.              保存对象

2)        栈的大小是可变的,通常以1MB为上限

三、托管堆

一个进程只有一个堆,这是在进程地址空间中的一个内存区域。所有统一进程中的线程都可以访问这个区域。就是说,堆与栈不同,对不专属于某个线程。堆的主要作用是存储对象。而且堆的大小象栈一样,在执行期间也是可以变化的,但是,堆大小的上限比栈的上限大得多。

四、对象存储|:托管线程栈与托管堆的比较

1)        堆的优点是容量比栈大得多

2)        栈的优点是存取速度比堆要快,这主要源于专门访问栈的IL指令。还有一个原因是访问展上的元素无需同步。

3)        因此,.NET设计成用堆来存储大对象而用栈来存储小对象

五、静态分配与动态分配的比较

1)        C++与C#有一个一致的地方,那就是对象要么分配在线程栈上(我们称为静态分配),要么分配在进程堆上(我们称为动态分配)

2)        C++与C#不同之处在于分配模式的选择的方式

                        i.              C++中对象的分配模式是由程序员自动选择的。代码中直接声明的对象将使用静态分配,如(int i=0)。当对象是使用new操作符时候采用动态分配(比特 int * pi = new int (0)

                      ii.              C#中对象的分配模式取决于对象的实现方式。值类型的实例采用静态分配,而引用类型的实例则使用动态分配

                    iii.              C#程序员的责任比C++程序员来说显出降低了

  1. 不需要选择对象的分配方式
  2. 不需要担心对象解除分配的问题。

六、引用类型与值类型

1)        .NET中每一种类型要么是值类型,要么是引用类型。值类型的实例通常是在线程栈上分配的,但是在某些情形下可以存储在堆中。引用类型的对象总是在进程堆中分配(动态分配)

七、公共类型系统CTS

1)        基本类型:指整数、浮点数、字符 和布尔等类型

2)        枚举

3)        结构

4)        类:都是引用类型。特别注意表示字符串的system.string类型和表示数组的system.array类型

5)        委托类型。它的实例可以应用一个方法,作用如同C++的函数指针

6)        指针。

八、对象比较

1)        objectA.equals(objectB)

2)        object.ReferenceEquals(objectA,objectB)

九、对象复制

1)        如果是值类型的实例,那么“=”复制运算符及iukeyi将源对象的状态逐字节地复制到目标对象中。而如果是引用类型的实例,“=”赋值运算符仅复制引用,而不是对象本身。因而引用类型需要一种复制引用类型的对象状态的方法。System.IConeable接口就是专门为这项工作准备的

2)        浅复制memberwiseclone()方法

class Article {

   public string Description;

   public int Price;

}

class Order : System.ICloneable {

   public int Quantity;

   public Article Article;

   public override string ToString() {

      return "Order: " + Quantity + " x " + Article.Description +

             "   Total cost: " + Article.Price * Quantity;

   }

   public object Clone() {

      // 浅复制

      return this.MemberwiseClone();

   }

}

class Program {

   static void Main() {

      Order order = new Order();

      order.Quantity = 2;

      order.Article = new Article();

      order.Article.Description = "Shoes";

      order.Article.Price = 80;

      System.Console.WriteLine(order);

      Order orderClone = order.Clone() as Order;

      orderClone.Article.Description = "Shirt";

      System.Console.WriteLine(order);

   }

}

 

以上例子的结果是

order:2*shoes total cost:160;

order:2*shirt total cost:160;

可以看到,对克隆订单的商品的修改反映到了原始订单的商品上。这是因为,这个程序中只有一个Article类的实例,两个order类都引用了这个唯一的实例。

3)        深复制

 

class Article : System.ICloneable {

   public string Description;

   public int Price;

   public object Clone() {

      // 此处,浅复制等于深复制

      return this.MemberwiseClone();

   }

}

class Order : System.ICloneable {

   public int Quantity;

   public Article Article;

   public override string ToString() {

      return "Order: " + Quantity + " x " + Article.Description +

             "   Total cost: " + Article.Price * Quantity;

   }

   public object Clone() {

      // 深复制

      Order clone = new Order();

      clone.Quantity = this.Quantity;

      clone.Article = this.Article.Clone() as Article;

      return clone;

   }

}

class Program {

   static void Main() {

      Order order = new Order();

      order.Quantity = 2;

      order.Article = new Article();

      order.Article.Description = "Shoes";

      order.Article.Price = 80;

      System.Console.WriteLine(order);

      Order orderClone = order.Clone() as Order;

      orderClone.Article.Description = "Shirt";

      System.Console.WriteLine(order);

   }

}

以上例子的结果是

order:2*shoes total cost:160;

order:2*shoes total cost:160;

这个例子中article类的浅复制与深复制是等价的,我们可以断定,针对一个给定的类,他的浅复制与深复制等价当且仅当所有成员均为值类型。不过article类中有一个字段是string类型,而他是引用类型,但string类有特殊性质,其中之一是它的实例都是不可变得。这个特性使得字符串在许多场合都和值类型的实力非常相似

4)        复制构造函数:这种构造函数接受一个我们想要使用的副本的类型作为参数

class Article : System.ICloneable {

   public string Description;

   public int Price;

   public object Clone() {

      return this.MemberwiseClone();

   }

}

class Order {

   public int Quantity;

   public Article Article;

   public override string ToString() {

      return "Order: " + Quantity + " x " + Article.Description +

             "   Total cost: " + Article.Price * Quantity;

   }

   // Default constructor.

   public Order() { }

   // 复制构造函数

   public Order( Order original , bool bDeepCopy) {

      this.Quantity = original.Quantity;

      if( bDeepCopy )

         this.Article = original.Article.Clone() as Article;

      else

         this.Article = original.Article;

   }

}

class Program {

   static void Main() {

      Order order = new Order();

      order.Quantity = 2;

      order.Article = new Article();

      order.Article.Description = "Shoes";

      order.Article.Price = 80;

      System.Console.WriteLine(order);

      Order orderClone = new Order( order , true );     

      orderClone.Article.Description = "Shirt";

      System.Console.WriteLine(order);

   }

}

十、  装箱与拆箱

1)        作为方法局部变量的值类型的实例是直接存储在线程栈上的。在本线程中使用这些值类型实例无需通过指针或引用。有些方法所需参数是引用类型object类,所有值类型都从object派生,但是值类型的实例没有引用,这个过程即装箱

class Program {

   static void f( object o ) { }

   public static void Main() {

      int i = 9 ;

      f( i );

   }

}

以上实例运行并不出错,正是装箱让我们获取了一个本来没有引用的值类型实例的引用,装操作分三步完成:

  1. 该值类型创建了一个新实例,并分配在堆中
  2. 这个堆中的实例根据栈中实例的状态进行初始化。在上面例子中,我们的证书进行了一次四字节的复制,可以说初始的对象实例被克隆了一份
  3. 用这个指向新创建的实例引用取代了原先在栈中分配的实例。

2)        相反的过程即拆箱

class Program {

   public static void Main() {

      int i = 9;

      object o = i;    // i is boxed

      int j = (int) o;  // o is unboxed

   }

}

3)        在C#中装箱和拆箱是隐式执行的。

十一、          基本类型

1)        C#没有unsigned关键字,现在用byte、ushort、uint、和ulong来表示无符号整数

在c#中long和ulong的大小是8字节

C#中decimal 16字节可以表示多达28位的有效数字的精确实数

C#中short是2字节

C#中int是32位

2)        关于代码的小问题

Int i=1000000000//i=10亿

Long j=10*I;

结果j不是100亿。实际上,这个计算是基于int类型计算的(10是int型),所以结果被复制到了一个long变量中。这里最大的问题是开发人员不会收到任何警告信息,除非使用了checked关键字。解决这个问题的方法是通知编译器希望使用8字节的整形,方法是将L加到字面常量后面

using System;

class Program {

   public static void Main() {

       int i = 1000000000;

       long j = 10L * i;

       Console.WriteLine(j);

   }

}

十二、          基本类型的运算

1)        5种基本算术运算符+-*/%

2)        5中基本运算符对应的赋值运算符

I+=j;i=i+j;

i-=j;i=i-j;

i*=j;i=i*j

i/=j;i=i/j;

i%=j;i=i%j;

3)        运算符的优先级

                      i.              +-×/的优先级高于%

                   ii.              可以用圆括号提升运算符的优先级

                iii.              两种不同的基本类型变量之间进行算术运算时,结果的类型将为两个类型中取值范围较大的一个。

                   iv.              任何整形和浮点型之间都允许强制类型转转换。可以用checked关键字。

4)        位运算

                      i.              <<左移位 相当于乘2

                   ii.              >>右移位相当于除2

                iii.             

 

十三、          结构

1)        结构是值类型,实例存储在栈中,因此结构不适宜太大。太大的结构最好用类代替;

2)        结构不能继承自其它的类或结构,也不能作为其他派生类或结构的基类;

3)        与类的字段不同,结构的字段不能在声明中显示初始化;

十四、          枚举和整形

1)        编译器默认将枚举的值设为int型整数;

2)        Object.Tostring()已经自动为每个枚举进行了覆写,作用是返回枚举常数定义时的名称的字符串;

3)        System.Enum类

String[] GetNames(Type type),返回一个枚举类型中所有值的名称的字符串数组

class Program {

   enum Maker { Renault, Ford, Toyota }

   static void Main() {

      foreach( string s in System.Enum.GetNames( typeof(Maker) ) )

         System.Console.WriteLine(s);

   }

}

 

十五、          字符串

1)        转义字符:\

2)        双引号\,反斜杠\\,空字符\0,回车符\r,水平制表符\t,单引号\

3)        无转义字符串常量:@ 将接受字符串常量中所有的换行。这特性在生成代码的时候非常有用

4)         

十六、          System.Text.StringBuilder

1)        Stringbuilder append()在字符串的结尾增加字符

2)        Stringbuilder insert (int index,)将字符插入到index指定的位置。位置为0表示插入到字符串头部

3)        Stringbuilder remove(int startindex,int length)将字符串从startindex到startindex+length位置的字符串删除。如果这两个位置之一小于0或者字符串的长度的长度就会引发argumentoutofrangeexception异常

class Program{

   static void Display(System.Text.StringBuilder s) {

      System.Console.WriteLine("The string : \"{0}\"",s);

      System.Console.WriteLine(" Length    : {0}", s.Length);

      System.Console.WriteLine(" Capacity  : {0}", s.Capacity);

   }

   public static void Main(){

      System.Text.StringBuilder s = new System.Text.StringBuilder("hello");

      Display(s);

      //The string : "hello"

      // Length    : 5

      // Capacity  : 16

     

      s.Insert( 4 , "--salut--" );

      Display(s);

      //The string : "hell--salut--o"

      // Length    : 14

      // Capacity  : 16

 

      s.Capacity = 18;

      Display(s);

      //The string : "hell--salut--o"

      // Length    : 14

      // Capacity  : 18

 

      s.Replace("salut","HELLO EVERYBODY");

      Display(s);

      //The string : "hell鈥擧ELLO EVERYBODY--o"

      // Length    : 24

      // Capacity  : 36

 

      s.EnsureCapacity(42);

      Display(s);

      //The string : "hell--HELLO EVERYBODY--o"

      // Length    : 24

      // Capacity  : 72

   }

}

 

十七、          委托类和委托对象

1)        C#允许用delegate关键字创建一种特殊的类,我们称之为委托类,委托类的实例称为委托对象

从概念上说,委托是一种指向一个或多个方法(静态或非静态)的引用。我们可以用调用方法的语法调用委托对象,这样会调用委托对象所引用的方法。

2)        委托类推测功能

public class Program {

  delegate void Deleg1();

  delegate string Deleg2( string s );

  static void f1() {

    System.Console.WriteLine("f1() called.");

  }

  static string f2(string s) {

    string _s=string.Format( "f2() called with the param \"{0}\"." , s );

    System.Console.WriteLine( _s );

    return _s;

  }

  public static void Main() {

      //查看IL语法,实际上还是调用了deleg1和deleg2委托类的构造函数

     Deleg1 d1 = f1; // 代替Deleg1 d1 = new Deleg1( f1 );

     d1();

     Deleg2 d2 = f2; // 代替  Deleg2 d2 = new Deleg2( f2 );

     string s = d2("hello");

  }

}

3)        委托对象和实例方法

委托可以以同样的方法引用实例方法。

using System;

public class Article {

   private int m_Price = 0;

   public Article( int price ) { m_Price = price; }

   public int IncPrice( int i ) {

      m_Price += i;

      return m_Price;

   }

}

public class Program {

   public delegate int Deleg( int i );

   public static void Main() {

      // Create an article with a price of 100.

      Article article = new Article( 100 );

      // Create a delegate object that references the 鈥業ncPrice()鈥?

      // method on the object 鈥榓rticle鈥?

      Deleg deleg = article.IncPrice;

      int p1 = deleg( 20 );

      Console.WriteLine("Price of article: {0}", p1 );

      int p2 = deleg( -10 );

      Console.WriteLine("Price of article: {0}", p2 );

   }

}

4)        System.Delegate类

  实际上,当一个委托对象引用多个方法时,每个方法都需要创建一个System.Delegate类的实例,实际上MulticastDelegate类的实例可以看成是一个System.Delegate类的实例的列表。

以下的代码好好学习

using System;

public class Article {

   public int m_Price = 0;

   public Article( int price ) { m_Price = price; }

   public int IncPrice( int i ) {

      m_Price += i;

      return m_Price;

   }

}

public class Program {

   public delegate int Deleg(int i);

   public static void Main() {

      Article a = new Article( 100 );

      Article b = new Article( 103 );

      Article c = new Article( 107 );

 

      // deleg 指向 ( a.IncPrice , b.IncPrice , c.IncPrice ).

      Deleg deleg = a.IncPrice;

      Deleg deleg1 = b.IncPrice;

      deleg1 += c.IncPrice;

      deleg += deleg1;

      deleg( 10 );

      Console.WriteLine( "a:{0} b:{1} c:{2}",

                         a.m_Price , b.m_Price , c.m_Price );

 

      //尝试移除子表 ( a.IncPrice , c.IncPrice )

      // 并不在委托对象deleg中

      Deleg deleg2 = a.IncPrice;

      deleg2 += c.IncPrice;

      deleg -= deleg2;

      deleg(10);

      Console.WriteLine( "a:{0} b:{1} c:{2}",

                         a.m_Price , b.m_Price , c.m_Price );

 

      //尝试移除子表( a.IncPrice , b.IncPrice ) 包含在委托对象deleg中

      Deleg deleg3 = a.IncPrice;

      deleg3 += b.IncPrice;

      deleg -= deleg3;

      deleg(10);

      Console.WriteLine( "a:{0} b:{1} c:{2}",

                         a.m_Price , b.m_Price , c.m_Price);

   }

}

 

 

posted on 2010-08-15 21:39  TsingCai  阅读(260)  评论(0编辑  收藏  举报