C# 学习笔记
2011-10-17 00:51
204 查看
类中的数据和函数称为类的成员。(类成员=数据成员+函数成员)
数据成员包含了类的数据——字段、常量、事件; 可以是静态数据(静态类中的数据)或实例数据(每个实例类拥有自己的实例副本)
函数成员提供了类中操作数据的某些功能,包括方法,属性,构造函数,析构函数,运算符以及索引器。
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#不支持多重实现继承,但是允许类型派生于多个接口。
不能建立结构的类型层次,但结构可以实现接口
数据成员包含了类的数据——字段、常量、事件; 可以是静态数据(静态类中的数据)或实例数据(每个实例类拥有自己的实例副本)
函数成员提供了类中操作数据的某些功能,包括方法,属性,构造函数,析构函数,运算符以及索引器。
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#不支持多重实现继承,但是允许类型派生于多个接口。
不能建立结构的类型层次,但结构可以实现接口
相关文章推荐
- C#学习笔记 委托
- C#开发范例大全--学习笔记
- SQLServer\framework启动报异常:Module的类型初始值设定项引发异常 [转]QQ空间、新浪微博、腾讯微博等一键分享API链接代码 window下 mongodb快速安装 数据表查询所有子/父节点 C#学习笔记1
- c#字符串学习笔记一
- C#学习笔记之 简单工厂模式2
- C# Infralution Licensing System学习笔记(二)网页程式Licensing应用
- C#委托与事件学习笔记
- C#学习笔记19——Windows服务创建及安装
- C#学习笔记一:委托、匿名函数、Lambda 表达式
- (原创)c#学习笔记10--定义类成员01--成员定义06--自动属性
- c# 学习笔记 二进制序列化
- ASP.NET MVC 学习笔记-2.Razor语法 ASP.NET MVC 学习笔记-1.ASP.NET MVC 基础 反射的具体应用 策略模式的具体应用 责任链模式的具体应用 ServiceStack.Redis订阅发布服务的调用 C#读取XML文件的基类实现
- 黑马程序员--学习笔记--c#基础flag标志位集锦
- C#学习笔记 事件
- 【卷土重来之C#学习笔记】(一)c#文章导航目录
- C#学习笔记11:C#中的顺序结构、分支结构、循环结构
- c# 异步编程 学习笔记
- C#学习笔记 5 运算符
- C#学习笔记21——文件、目录、注册表操作
- C#学习笔记(四)