C# 学习笔记

来源:互联网 发布:2017ipad视频软件 编辑:程序博客网 时间:2024/04/16 16:53

类中的数据和函数称为类的成员。(类成员=数据成员+函数成员)

数据成员包含了类的数据——字段、常量、事件; 可以是静态数据(静态类中的数据)或实例数据(每个实例类拥有自己的实例副本)

 

函数成员提供了类中操作数据的某些功能,包括方法,属性,构造函数,析构函数,运算符以及索引器。

 

ref参数

在方法中使用引用传递参数,改方法对参数所做的改变将会影响原来的值,

定义的时候:public void somefuntion(int[] ints,ref int i)

调用的时候:somefuntion(ints,ref i) //调用方法时,需要添加 ref 关键字

传递参数的时候,无论是按值传递还是按引用传递,参数都要先初始化

 

out 关键字

在方法的输入参数中加上out关键字的时候, 参数可以不用初始化, 执行方法后,方法对参数进行的修改会保留下来,在调用的时候,要在参数前加 out

定义的时候:public void somefuntion(int[] ints,out int i)

调用的时候:somefuntion(ints,out i)

如果在方法中没有给out 参数分配一个值,那么方法就不能编译

 

方法的重载

两个方法不能仅在返回类型上有区别;

不能仅根据参数是声明为ref或者out来区分;

 

属性的概念是:它是一个方法或一对方法,在客户机代码看来,它是一个字段

private string attribute;

public string Attribute

{

get{return attribute;}

set{attribute=value;}

}

自动实现的属性

如果属性的set和get访问器中没有任何逻辑,可以使用自动实现的属性,这种属性会自动实现基础成员变量。

public string Attribute{get ;  set ; }

 

带修饰符的属性

属性可以有公共的get访问器和受保护或者私有的set访问器

在get set访问器中,必须有一个具备属性的访问级别,如果get访问器的访问级别是protected ,就会产生一个编译错误,因为这会使两个访问器的访问级别都不是属性

public string Attribuet{ get ; private set; }

使用自动实现的属性,就不能在属性设置中进行属性的有效性验证。而且必须有两个访问器,尝试把属性设置为只读属性,就会出错。

 

构造函数

如果没有提供构造函数,编译器会在后台创建一个构造函数,把所有的成员字段初始化为默认值;

如果提供了带参数的构造函数,编译器就不会自动提供默认的构造函数了

私有构造函数的作用:

类仅用作某些静态成员或属性的容器,因此永远不会实例化;

希望类仅通过调用某个静态成员函数来实例化(对象实例化类的代理方法)  ????

 

 

静态构造函数

可以给类编写静态的无参数的构造函数,这种构造函数只会执行一次。编写静态构造函数的原因是,类中有一些静态字段或属性,需要在第一次

使用类之前,从外部源中初始化静态字段或属性。静态构造函数通常在第一次调用类的成员之前执行

一个类只能有一个静态构造函数, 不用写修饰符,不能带任何参数

 

从其他构造函数中调用构造函数——构造函数初始化器

 

构造函数初始化器在构造函数之前执行.

C#的构造函数可以包含对同一个类的另一个构造函数的调用,也可以直接包含对基类的构造函数的调用

c#初始化符中的代码只能调用另一个构造函数

public car

{

private string description;

private unit nwheels;

public car(string description,uint nwheels)

{

this.description=description;

this.nwheels=nwheels;

}

public car (string description) : this ( mode l , 4 )//调用参数最匹配的那个构造函数

//public car(string description) :base(model,4) //调用基类最匹配的那个构造函数   初始化符中不能有多个调用

{

 

}

}

 

 只读字段

readonly允许把一个字段设置为常量,当可以执行一些运算,以确定它的初始化值,可以在构造函数中给给只读字段赋值,或者声明的时候给初始化值,

如果没有赋值,它的值就是数据类型的默认值。

注意:不能在别的地方赋值

public class DocumentEditor

{

   public  static readonly uint  MaxDocument;

   static DocumentEditor()

{

MaxDocument=DosomethingToFindOutMaxDocument();

}

}

只读字段是静态的,就在静态构造函数中初始化

如果只读字段是实例字段,就要在实例构造函数中初始化

 

匿名类型

var关键字,用于隐式类型化的变量。

当var和new关键字一起使用时,可以创建匿名类型

匿名类型只是一个继承了Object,没有名称的类,该类的定义从初始化器中推断,类似于隐式类型化的变量。

var captain=new{FristName="Joke",MiddleName="M",LastName="Joker" };//生成一个带有FristName,MiddleName,LastName属性的对象

var doctor=new{FirstName="James",MiddleName="",LastName="Bonde"};

captain 和doctor的类型就是相同的,,可以设置captain=doctor

如果有一个具有FristName,MiddleName,LastName 属性的类,该类的实例为person,那么captain对象可以初始化为

var captain=new{person.FristName,person.MiddleName,LastName};//类的属性名投射为新对象名captain,captain具有这三个属性;

这些新对象的类型是未知的,只有编译器才能使用它们。

不能也不应该使用新对象上的任何类型引用,因为这不会得到一致的结果。

 

结构:

类保存在堆中,在数据的生存周期中获得了很大的灵活性,,但性能会损失

为结构定义函数与类定义函数完全相同

struct Dimensions

{

     public double Length;

      public double Width;

      Dimensions(double length,double width)

       {

            Length=length;

              Width=width;

       }

       public double Diaqonal

          {

                 {

                        get

                            {

                                    return Math.sqot(Length*Length+Width*Width);

                            }

                 }

           }

}

 

结构与类的区别:

   结构是值类型,类是引用类型,结构存储在堆栈中或存储为内联(如果它们是一个另外保存在堆上的对象的一部分),生存期的限制跟简单的数据类型一样;

结构不支持继承;

结构构造函数工作方式的区别。编译器总是提供一个无参数的默认构造函数,这是不允许替换的。类的构造函数中,如果指定了带参数的构造函数,编译器使用带参数的构造函数初始化,不会提供一个无参数的默认构造函数;

使用字段,可以指定字段如何在内存中布局

 

 

 

编写.net代码的原则:字段(除const字段之外)应总是私有的,并由公共属性封装

 

 Dimensions point=new Dimensions();//因为结构是值类型,所以new运算符与类和其他引用类型的工作方式不同,这里的new运算符并不分配堆中的内存,而是调用相应的构造函数,根据传送给它的参数的值,初始化所有字段

point.Length=3;

point.Width=4;

 

等效于:

Dimensions point;//对于结构,声明实际是为整个结构分配了堆栈中的空间,所以就可以赋值了

point.Length=3;

point.Width=4;

 

Dimensions point;

double d=point.Length; //编译错误,使用了未初始化的变量

结构遵循其他数据类型都遵循的原则,在使用前,所有的元素都必须初始化,在结构上调用new运算符,或者给所有的字段赋值,结构就完全初始化了

 

如果结构定义为类的成员字段,在初始化对象的时候,该结构会自动初始化为0

结构正面影响:为结构分配内存时,速度非常快,因为它们将内联或者保存在堆栈中,超出作用域被删除时,速度也非常快

负面影响:把一个结构赋值给另一个结构的时候,结构的所有内容都被复制,这样根据结构的大小,性能的损失也不同。对于类,只是复制引用,。

 

当把结构作为参数传递给方法的时候,可以把它作为ref参数传递,此时传递的是内存的地址,传递速度就与在类中传递的速度一样快了。但是要注意,如果这样做,被调用的方法就可以改变结构的值了

 

结构和继承

结构不是为继承设计的,不能 从一个结构中继承。唯一的例外是结构派生于类System.Object,因此结构可以访问System.Object的方法,甚至可以重写System.Object中的方法

结构的继承链是:结构派生于System.ValueType,System.ValueType派生于System.Object 。

不能为结构提供其他基类,每个结构都派生于System.ValueType

 

结构的构造函数

为结构定义构造函数的方式与类定义构造函数的方式相同,但是不允许定义无参数的构造函数 .net运行库不能调用用户提供的定制的无参数的构造函数,禁止在C#的结构内使用无参数的构造函数。

默认构造函数总是把所有的字段都初始化为0,且总是隐式提供的。即使提供了带参数的构造函数,也不能为字段提供初始化值。会产生一个编译错误。

 

 

 

部分类

partial关键字允许把类、结构、和接口放在多个文件中。

partial关键字的用法是 把partial放在 class 、struct、interface关键字的前面

如果声明类时使用了下面的关键字,那么这些关键字将应用于同一个类的所有部分:

public、protect、private、internal、abstract、sealed、new、一般约束

 

在嵌套类型中,只要partial 位于class 关键字的前面,就可以嵌套部分类了,在把不分类编译到类型的时候,会合并属性、xml注释、接口、泛型类型参数的属性和类型,继承关系

 

 静态类

静态构造函数,初始化静态的成员变量。如果类只包含静态的方法和属性,这个类就是静态的。不能创建静态类的实例,编译器检查是否添加了类的成员,如果是,就生成一个编译错误

static class StaticUtilities

{

       public static void HelperMethod()

        {

        }

}

 调用:StaticUtilities.HelperMethod();

 

System.Object方法

ToString()方法“获取对象字符串表示的一种方式,在数据格式化方面,提供的选择比较少。如果需要专业的字符串表示,可以考虑用户的格式化配置,或者使用区域,就应是想IFormattable接口

GetHashTable()方法 如果对象放在散列表或字典的数据结构中,,就可以使用这个方法,以确定对象放在结构的什么地方,如果希望把类当做字典的一个键,就应该重写该方法。

Equals()(两个版本) 和ReferenceEquals()方法  这三个方法更比较运算符==在使用方式上有微妙的区别

Finalize()方法当引用对象被回收,清理资源时调用。Finalize()方法的Object执行代码实际上什么都没有做,因而被垃圾回收期忽略。

如果对象拥有未托管资源的引用,则在对象删除时,需要删除这些引用,此时一般重写Finalize()方法

GetType()方法:这个方法从System.Type派生的类的一个实例提供所属类的消息

MemberWiseClone()方法:复制对象,返回一个对副本的引用,得到的副本是浅表复制,即复制了类中所有的值类型。

如果类中包含嵌套的引用,则只负责引用,不复制引用的对象。这个方法是受保护的,不能用于复制外部的对象,不能重写

 

 

扩展方法

 当给对象添加功能,如果没有源码,可以使用扩展方法,允许改变一个类,但是不需要类的源码

扩展方法是静态方法,是类的一部分,但是实际上没有放在类的源码中。

public static class Extension

{

     public static void AddToMount(thisMoney money,decimal amountToAdd) //对于扩展方法,第一个参数是要扩展的类,放在this关键字的后面,告诉编译器,这个方法是类 Money的一部分。扩展方法中,可以访问所扩展类的所有的公共方法和属性

{

money.Amout+=amountToAdd;

}

}

如果扩展方法与类的某个方法同名,扩展方法将不会被调用。类中一有的实例方法优先

 

继承

实现继承和接口继承

实现继承:表示一个类型派生于一个基类型。拥有该基类型的所有字段和函数。

接口继承”表示一个类型只继承了函数的签名,没有继承任何实现代码,在需要指定该类型具有某些可用的特性时,最好使用这种继承。

 

C#不支持多重实现继承,但是允许类型派生于多个接口。

不能建立结构的类型层次,但结构可以实现接口

 

 

 

 

 

原创粉丝点击