读书笔记之《C#入门经典》基础篇

         总结一些在学习《C#入门经典》一书中的技巧细节以及基础知识点,由于本人是一个objective-c程序员,所以会偶尔碰到C#与objectiv-c比较类似的概念会提醒一下,下面是基础篇:

1.主动进行垃圾回收检查。.NET垃圾回收会定期检查计算机内存,从中删除不再需要的内容。这种检查不定时,因此需要许多内存才能运行的代码应该自己执行这样的检查,而不是坐等垃圾回收。

2.C#代码是区分大小写的,必须使用正确的大小写形式输入代码。

Debug.Log("C# Programming!"); //正确的大小写字母
DEBUG.LOG("C# Programming!");//错误,不能通过编译
Debug.log("C# programming!"); //错误的大小写形式,不能通过编译

3.#region和#endregion关键字,使用来定义可以展开和折叠的代码区域的开头和结尾。这有点类似与Objective-C里的#pragma mark 可以给代码划分段落,提高代码的可读性。

#region define datas
int a = 10,b = 100;
string userName = "user0";
#endregion

4.checked和unchecked关键字,用来检查表达式的上下文是否溢出。

byte destVar;
short sourceVar = 281;
destVar = (byte)sourceVar;
Debug.Log("sourceVar = " + sourceVar);
Debug.Log("destVar = " + destVar);
// 打印结果如下:sourceVar = 281 destVar = 25 为什么呢?因为byte可存储的最大值是255.使用checked关键字可以避免类似的问题。
byte destVar;
short sourceVar = 281;
destVar = checked((byte)sourceVar);
Debug.Log("sourceVar = " + sourceVar);
Debug.Log("destVar = " + destVar);
//执行这段代码,程序会崩溃并显示错误信息4.checked和unchecked关键字,用来检查表达式的上下文是否溢出。


5.使用Convert命令进行显示转换。比如:Convert.ToDouble(var);如果不能转换,编译器会告诉用户。                                                                                                                                               

6.使用ref关键字指定参数来实现引用传递参数,通过引用参数可以实现改变用作参数的多个变量值,解决函数只能返回一个返回值的局限性。

static void PowNum(ref int var) {
   var = var * var;
}
//使用还必须指定ref参数
int number = 8;
PowNum(ref number);
//注意,用作ref参数的变量有两个限制。1、函数可能会改变引用参数的值,必须在函数调用中使用“非常量”变量。2、必须使用初始化过的变量。C#不允许ref参数在使用他的函数中初始化。比如下面的用法是错误的
错误用法1:
const int number = 8;
PowNum(ref number);
错误用法2:
int number;
PowNum(ref number);

7.out关键字也可以实现传递值,指定所给的参数是一个输出参数,使用方式与ref关键字相同。但是存在一些区别:把未赋值的变量用作ref参数是非法的,但可以把未赋值的变量用作out参数;另外,函数使用out参数时,out参数必须看作未赋值。

static void PowNum(out int var) {
    var = 10;
    var = var * var;
}
int var;
PowNum(out var);
//此时var值为100

8.结构函数;

struct UserInfo {
  pubilc string firstName, lastName;
  public string UserName () {
      return firstName + lastName;
  }
}

 9.委托是一种可以把引用存储为函数的类型。委托的声明非常类似于函数,但不带函数体,且要使用delegate关键字。见例子:

class Demo {
  delegate double HandleNumberDelegate (double num1, double num2);
  static double Add(double num1, double num2) {
   return num1+ num2;
  }
   static double substract (double num1, double num2) {
   return num1 - num2;
  }
  static void Main() {
      HandleNumberDelegate handleNumDelegate;
      double num1 = 100, num2 = 40;
      string input = Console.ReadLine();
      if ("A" == input) 
          handleNumDelegate = new handleNumberDelegate(Add);  //这是委托赋值的一个独特语法,可以直接写成handleNumDelegate = Add;
     else 
          handleNumDelegate = new handleNumberDelegate(substract);
     Debug.Log("HandleNum Res = " + handleNumDelegate(num1,num2));
  }
}

10.调试打印函数

//1.非中断模式的打印函数
Console.WriteLine()
Debug.WriteLine()  //发布版本不会编译这个语句
Trace.WriteLine() //发布版本也可以打印

Console.Write()
Debug.Write()
Trace.Write()

Debug.WriteLineIf()
Trace.WriteLineIf()
Debug.WriteIf()
Trace.WriteIf()
//2,中断模式的打印函数
Debug.Assert(null != var, "var is null","Assertion occurred in main()");
Trace.Assert()


11.错误处理

 try {

.... //包含抛出异常的代码

}

catch (<exceptionType> e) {

... //包含要抛出异常要执行的代码,可以提供多个catch块,<exceptionType> 设置为只响应特定的异常类型(如:System.IndexOutOfRangeException)。还可以忽略这参数,响应所有的异常

}

finally {

...//包含总是会执行的代码,如果没有异常,则在try块之后执行;如果处理了异常,则在catch块之后执行

}


12.接口是把公共实例方法和属性组合起来,以封装特定功能的一个集合。注意,接口不能单独存在,不能实例化,不能包含实现其成员的任何代码,实现过程必须在实现接口的类中完成。接口也是可以继承的。接口成员的定义与类成员的定义类似,但有几个重要的区别:

   不允许使用访问修饰符(public、private、protected 或 internal),所有的接口成员都是公共的。

   接口成员不能包含代码体。

   接口不能定义字段成员。

   接口成员不能用关键字static、virtual、abstract、sealed来定义。

   类型定义成员是禁止的。

   实现接口的类必须包含该接口所有成员的实现代码。而且必须匹配指定的签名(包括匹配指定的get和set块),并且必须是公共的。可以使用virtual或abstract来实现接口成员,但不能使用static或const。

    隐式实现的接口成员可以通过类和接口访问,而显式实现的接口成员只能通过接口访问。

    如果在定义属性的接口中只包含set块,就可以给类中的属性添加get块,反之亦然。但是只有所添加的存取器的可访问修饰符比接口中定义的存取器的可访问修饰符更严格时,才能这么做。

public interface IBaseInterface {
  int GIntProperty {
      get;
   }
  void DoSomething ();
  void DoSometingElse ();
}
public class BaseClass {
 public virtual void DoSomethimg () {
  }
}

public class DerivedClass:BaseClass, IBaseInterface {
  public int GIntProperty {get; protected set;}
  public void IBaseInterface.DoSomethingElse () { //显示实现接口,不能通过类的实例来访问,
   }
}
DerivedClass derivedObj = new DerivedClass ();
IBaseInterface baseInterface = derivedObj;
baseInterface.DoSomethingElse ();

13.关于C#类的修饰符关键字public class MyClass { // class members }  ,默认情况下,类声明为内部的,默认为internal访问修饰符关键字修饰,只能在当前的项目中的代码才能访问它。而用public显式指定类是公共的,可以被其他项目访问。编译器不允许派生类的可访问性高于基类,也就是internal类可以继承于一个public类,但一个public类不能继承于一个内部类。

     可以用abstractsealed来修饰类,其中abstract键字指定类是抽象的,不能被实例化,只能继承,可以有抽象成员,sealed键字指定类是密封的,不能被继承。比如:public abstract class MyClass { //类成}

     可以在类中指定继承和接口。基类只能有一个,但是接口可以指定多个。如果指定了基类,它必须紧跟在冒号的后面,之后才是指定的接口。如果没有指定基类,则接口就跟在冒号的后面。必须使用逗号分隔基类名和接口名。例子:public class MyClassMyBaseIMyInterfaceISecInterface  { // 类成}

      base键字在C#边有点类似与objective-c类里的super的概念,就是表示基类的对象实例。this键字在c#边类似objective-c类里的self概念,表示当前类的对象实例自身。


14.义类成员的访问级别关键字

    public-----员可以由任何代码访问,

    private------员只能由类中的代码访问(如果没有任何关键字,C#语言默认使用这个关键字,PS:貌似各个语言的默认关键字不一样的,比如objective-c语言的类成员的默认关键字是protected

    internal--------员只能由定义它的程序集(项目)内部的代码访问

    protected----------员只能由类或派生类中的代码访问。PSprotected internal组合使用表示类成员只能由程序集中的派生类的代码来访问。

    readonly--------表示类成员只能在执行构造函数的过程中赋值,或有初始化赋值语句赋值。

    static-------义类成员为静态,必须通过他们的类来访问,比如:Class.ClassIntMember.而不是通过这个类的实例来访问

    const-----义类成员为不可以修改,也是静态的。


15.义类方法的关键字

    static------同类成员一样,静态的方法只能通过类来访问,不能通过对象实例来访问。

    virtual-------虚函数,方法可以重写。 

    abstract------方法必须在非抽象的派生类中重写(只用于抽象类中)  

    override-----方法重写了一个基类方法(如果方法被重写,必须使用该关键字)。如果使用了override还可以使用sealed指定在派生类中不能对这方法做进一步的修改,即这个方法不能由派生类重写

   extern-------方法定义放在其他地方,可以在项目外部提供方法的实现代码。

   例子:

public class MyClass:BaseClass {
     public override sealed void DoSomething () {
       //
     }
}
     

16.义属性,属性拥有两个类似于函数的块,一个块用于获取属性的值,另一个用于设置属性的值,分别称为get访问器和set访问器。每个访问器也可以有自己的可访问性,但是访问器的访问性不能高于它所属的属性,私有属性的访问器不能包含任何可访问修饰符。属性可以使用virtualoverrideabstract键字,就像方法一样。

public class MyClass {
  private int gInt;
  public int GInt {
     get {
         return gInt; 
     }
     protected set {
       gInt = value;
     }
  }
}

17.隐藏基类方法。使用new键字可以显示地在派生类中隐藏基类的方法。

public class BaseClass {
 public void DoSomethimg () {
   Debug.Log("In Base");
  }
}

public class DerivedClass:BaseClass {
  new public void DoSomething () {
     Debug.Log("In Derived");
 }}
DerivedClass derivedObj = new DerivedClass();
BaseClass baseObj;
baseObj = derivedObj;
baseObj.DoSomething ();
//打印结果:In Base

        注意隐藏基类成员和重写它们的区别。重写方法是将替换基类中的实现代码,即使是通过基类类型进行访问,也仍然是调用派生类的方法(多态性)。但是new键字隐藏基类的实现代码,仍然可以通过基类访问它。

public class BaseClass {
 public virtual void DoSomethimg () {
   Debug.Log("In Base");
  }
}

public class DerivedClass:BaseClass {
  public override void DoSomething () {
     Debug.Log("In Derived");
   }
}
DerivedClass derivedObj = new DerivedClass();
BaseClass baseObj;
baseObj = derivedObj;
baseObj.DoSomething ();
//打印结果:In Derived

        无论是重写成员还是隐藏成员,都可在派生类中访问基类成员。要对派生类的用户隐藏继承的公共成员,但仍能在类中访问其功能。要给继承的虚拟成员添加实现代码,而不是简单地用重写的新代码替换它。要实现以上目的,可以使用base键字,可以包含在派生类中的基类实现代码。

public class BaseClass {
 public virtual void DoSomethimg () {
   //基类的实现
   Debug.Log("In Base");
  }
}

public class DerivedClass:BaseClass {
  public override void DoSomething () {
      base.DoSometing(); //是不是很类似objective-c中的super?
     //派生类的实现代码
     Debug.Log("In Derived");
   }
}

     对于接口,同样也可以用关键字new隐藏基接口的成员。

interface IBaseInterface {
  void DoSomething ();
}

Interface IDerivedInterface : IBaseInterface {
  new void DoSomething () ;
}

18.部分类定义,使用partial键字来定义部分类,将类的定义放在多个文件中。例如:属性、字段放在一个文件中,而方法放在另一个文件中。只需要在每个包含部分类定义的文件中对类使用关键字partial即可。应用与部分类的接口也会应用于整个类。部分类也可以定义部分方法,但没有方法体,在另一个部分类中包含实现代码。部分类定义可以在一个部分类定义文件或多个部分类定义文件中包含基类。但是如果基类在多个定义文件中指定,它就必须是同一个基类。

public partial class MyClass :BaseClass {
  partial void DoSomething ();
}

public partial class MyClass: BaseClass {
   partial void DoSomething () {
     Debug.Log("In DoSomething");
  }
}

      注意,部分方法可以是静态的,但它们总是私有的,而且不能有返回值。它们使用的任何参数都不能是out参数,但可以是ref参数。部分方法也不能使用virtualabstractoverridenew sealedextern饰符。


19.集合。C#中的System.Collections名称空间的几个接口提供了基本的集合功能:

      IEnumerable可以迭代集合中的项。

      ICollection继承于IEnumerable获取集合中项的个数,并把项复制到一个简单的数组类型中。

      IList继承于IEnumerableICollection)提供了集合的项列表,允许访问这些项,并提供其他一些与项列表相关的基本功能。

      IDictionary继承于IEnumerableICollection)类似于IList,但提供了可通过键值(而不是索引)访问的项列表。

      其中System.Collections.ArrayList是一个可变数组。简要介绍其一些方法,具体可MSDN的官方文档。可以通过索引访问其成员,Add()方法添加新项;可以使用foreach函数遍历数组成员;Count属性获取数组个数; Remove()RemoveAt()方法删除项,AddRange()方法一次添加好几个项,IndexOf()方法获取对象在数组中的索引。


20。类型比较,GetType方法,所有的类都从System.Object继承了这个方法,这个方法和typeof()运算符一起使用,就可以确定对象的类型。

if (myObj.GetType() == typeof(MyClass)) {
  //myObj是MyClass类的一个实例
}

     封箱和拆箱,封箱就是将值类型转换为System.Object类型,或者转换为由值类型实现的接口类型。拆箱则是相反的转换过程。 

      is运算符,可以检查对象是否是给定类型或者是否可以转化为给定类型,如果是,这个运算符就返回true 

if (myObj is MyClass) {
  //myObj 是MyClass类的一个实例
}

21.类型转换。as运算符可以把一种类型转换为指定的引用类型,如果不能转换,表达式的值就是null

class ClassA {
// ....
}

class ClassB : ClassA {
//...
}

ClassA obj1 = new ClassA ();
ClassD obj2 = obj1 as ClassD; //obj2 是null



猜你喜欢

转载自blog.csdn.net/eric_XJJ/article/details/8628701
今日推荐