C#与C++的区别(二)
2017-09-16 11:18
169 查看
这几天深入学习C#的面向对象的内容,发现C#的很多用法跟C++比起来还是有很多的不同点,头脑中知识的海洋刮起了阵阵海浪,在此继续整理一下二者的不同点,主要还是写的C#能用,而在C++中不能用的一些知识。(以下都是C#的用法)
类的构造函数也可以通过关键字this调用同一个类的另一个构造函数,例如:
托管资源 ,如简单的int,string,float,DataTime等等,是不需要人工进行回收的
非托管资源,例如文件,窗口或网络连接
.(1)NET Framework提供Obeject.Finalize方法,在默认情况下,Finalize不执行任何操作,有需要的话可以覆盖
通过析构函数可以自动生成对Finalize方法和对基类的Finalize方法的调用。
但是需要注意的是:如果试图既编写析构函数,又编写Finalize方法的话,将导致编译器报错。
(2)实现非托管资源的释放回收时,采用Dispose()方法
实现Dispose()方法时,一定要加上"GC.SuppressFinalize(this)"语句。作用是抑制析构函数的执行。
体验一下把
注意:类方法只能访问静态变量,访问非静态变量的尝试会引起编译错误。
所有C#中没有全局变量,要想实现全局变量相同的功能,可以在类内定义一个静态变量,然后通过“类名.静态变量”的形式调用。静态变量只有在执行完以后才会回收。
静态构造函数的典型用途是:
当类使用日志文件时,将使用这种构造函数向日志文件中写入项。
当字段声明中包括readonly修饰符时,该字段成为只读字段。只能在声明只读字段的时候赋予初值。其他任何时候都不允许为只读字段赋值。
但是,如果在类定义中的时候显式的添加一个构造函数,可以在构造函数中改变只读字段的值。
注意:在静态方法体内不能够直接使用非静态成员,也没有this引用,因为没有实例可以引用。
使用ref型参数时,传入的参数必须先被初始化。对out而言,必须在方法中对其完成初始化。(代码出区别)
使用ref和out时,在方法的参数和执行方法时,都要加Ref或Out关键字。以满足匹配。
out适合用在需要retrun多个返回值的地方,而ref则用在需要被调用的方法修改调用者的引用的时候。
ref是 有进有出,而out是 只出不进。
创建一个属性包括两步:
声明一个字段来存储属性值
编写一个属性·声明,提供一个访问接口
可以说,属性是一种特殊的方法,但是属性和方法还是有不同之处:
属性不用使用圆括号,但方法一定要有圆括号
属性不能指定参数,但是方法可以指定参数
属性不能使用void类型,方法介意使用void类型
属性使用方法和变量相同
与成员属性不同:
它可以接受1个或多个参数
使用this关键字作为索引器的名字
1.类的构造函数
可通过初始值设定项来调用基类的构造函数,例如:public Student(string no,string name,char sex,int age):base(name,sex,age) {......}这是调用父类的用法;
类的构造函数也可以通过关键字this调用同一个类的另一个构造函数,例如:
public Point():this(0,20) {......}其中this先执行,而point的大括号内的代码后执行
2.私有构造函数
在某些特殊的情况下,使用私有构造函数能够表达意想不到的效果。比如,想建立这样一个类,不允许被对象实例化,但提供对外的静态接口成员;public class filling { private filling(){};//私有构造 public static void happy() { Console.WriteLine("Happy!"); } public static void sad() { Console.WriteLine("Sad!"); } } public class MainClass { public static void Main() { //filling f1=new filling();//不能实例化 filling.happy(); filling.sad(); } }
3.析构函数
C#支持析构函数。虽然C#能够自动进行垃圾回收,但对于某些资源,.Net不知道如何回收,所以需要人工的内存回收。托管资源 ,如简单的int,string,float,DataTime等等,是不需要人工进行回收的
非托管资源,例如文件,窗口或网络连接
.(1)NET Framework提供Obeject.Finalize方法,在默认情况下,Finalize不执行任何操作,有需要的话可以覆盖
通过析构函数可以自动生成对Finalize方法和对基类的Finalize方法的调用。
但是需要注意的是:如果试图既编写析构函数,又编写Finalize方法的话,将导致编译器报错。
(2)实现非托管资源的释放回收时,采用Dispose()方法
实现Dispose()方法时,一定要加上"GC.SuppressFinalize(this)"语句。作用是抑制析构函数的执行。
/* * Created by SharpDevelop. * User: tianyu * Date: 2017/9/16 * Time: 10:43 * * To change this template use Tools | Options | Coding | Edit Standard Headers. */ using System; public interface IDisposable { void dispose(); } class myFile:IDisposable { public myFile(){} public void close(){} public void dispose() { close(); Console.WriteLine("Close"); //GC.SuppressFinalize(this); } ~myFile() { Console.WriteLine("Deconstructor"); } } class Program { public static void Main(string[] args) { myFile file=new myFile(); file.dispose(); Console.ReadLine(); } }
体验一下把
GC.SuppressFinalize(this);注释掉和不注释的结果
4.静态方法
类方法是不需要类的任何实例都可以被调用的方法,在方法生命中用static关键字表示,通过类名调用。注意:类方法只能访问静态变量,访问非静态变量的尝试会引起编译错误。
5.静态构造函数(感觉这个贼好玩)
特别注意的是:静态构造函数只会执行一次,而且是在类中第一个对象初始化或者是引用任何静态成员之前执行。所有C#中没有全局变量,要想实现全局变量相同的功能,可以在类内定义一个静态变量,然后通过“类名.静态变量”的形式调用。静态变量只有在执行完以后才会回收。
静态构造函数的典型用途是:
当类使用日志文件时,将使用这种构造函数向日志文件中写入项。
/* * Created by SharpDevelop. * User: tianyu * Date: 2017/9/16 * Time: 11:02 * * To change this template use Tools | Options | Coding | Edit Standard Headers. */ using System; namespace static_contrutor { class Student { public int serialNum; private static int counter; static Student()//静态构造函数 { Random rand 10282 =new Random(); counter=rand.Next(0,1000); Console.WriteLine("static Contructor={0}",counter); } public Student() { serialNum=counter; counter++; Console.WriteLine("Constructor"); } } class Program { public static void Main(string[] args) { Student s=new Student(); Console.WriteLine("{0}",s.serialNum); Student s1=new Student(); Console.WriteLine("{0}",s1.serialNum); Console.ReadLine(); } } }
6.类的字段成员——只读字段
当字段声明中包括readonly修饰符时,该字段成为只读字段。只能在声明只读字段的时候赋予初值。其他任何时候都不允许为只读字段赋值。但是,如果在类定义中的时候显式的添加一个构造函数,可以在构造函数中改变只读字段的值。
using System; namespace readOnly { class Program { public readonly string str1="i am str"; public Program() { str1="i am not str"; } public static void Main(string[] args) { Program p=new Program(); Console.WriteLine(p.str1); Console.ReadLine(); } } }
7.类的方法成员--静态方法
使用static静态字来修饰。静态方法不需要类实例,直接使用“类名.方法”格式调用即可;注意:在静态方法体内不能够直接使用非静态成员,也没有this引用,因为没有实例可以引用。
public class operat { public long add(long a,long b) { return a+b; } public double add(double a,double b)//重载 { return a+b; } public static void hi() { Console.WriteLine("hi"); //add(3,5);不能再静态函数体内访问非静态成员 } } //可以再Main函数体内访问operat.hi(),因为Main函数本身就是静态函数
8.参数传递--主要思考地址传递(ref和out)
对于初学者来说,ref和out经常分不清各自的功能,于是我整理了一波二者的区别:使用ref型参数时,传入的参数必须先被初始化。对out而言,必须在方法中对其完成初始化。(代码出区别)
class RefExample { static void Method(ref int i) { i = 44; } static void Main() { int val = 0; Method(ref val); // val is now 44 } }
class OutExample { static void Method(out int i) { i = 44; } static void Main() { int value; Method(out value); // value is now 44 } }
using System; class Program { static void Main() { Program obj = new Program(); int score = 55; //声明原来分数 int refscore, outscore; //声明两个变量 obj.ChangeScore(score, ref refscore, out outscore); Console.WriteLine("您原来的分数是{0},调整后的分数为{1},加平时表现分后{2}", score, refscore, outscore); Console.ReadKey(); } private void ChangeScore(int score, ref int refscore, out int outscore) { if (score > 50 && score < 60) { refscore = 60; } if (refscore > 60) { outscore = refscore + 5; } } }
使用ref和out时,在方法的参数和执行方法时,都要加Ref或Out关键字。以满足匹配。
out适合用在需要retrun多个返回值的地方,而ref则用在需要被调用的方法修改调用者的引用的时候。
ref是 有进有出,而out是 只出不进。
9.参数数组
在不确定需要传递多少个参数的时候使用params关键字指明一个可变的参数数组。数组参数的类型必须是一维数组,而且是形参表上的最后一个参数,对于值类型,数组参数是值传递方式进行传递,且不能用ref或out与params进行组合。namespace param { class Program { public static double averge(params int[]nums) { int sum=0; int cnt=0; foreach(int i in nums) { sum+=i; cnt++; } return (sum/cnt); } public static void Main(string[] args) { double d=averge(13,13,16,27); Console.WriteLine("average={0}",d); Console.ReadLine(); } } }
10.属性成员
属性主要用于描述和维护类对象的状态。对属性的访问就好像是直接访问public字段的成员,但在类内部是通过类方法访问的。创建一个属性包括两步:
声明一个字段来存储属性值
编写一个属性·声明,提供一个访问接口
class Program { private string propVal; public string str//声明属性str { get//返回存在私有变量的属性值 { return propVal; } set//存储属性值到私有变量 { propVal=value; } }
可以说,属性是一种特殊的方法,但是属性和方法还是有不同之处:
属性不用使用圆括号,但方法一定要有圆括号
属性不能指定参数,但是方法可以指定参数
属性不能使用void类型,方法介意使用void类型
属性使用方法和变量相同
11.索引器
参数成员属性:set、get方法与成员属性不同:
它可以接受1个或多个参数
使用this关键字作为索引器的名字
namespace photo { class Photo { string title; public Photo(string title) { this.title=title; } public string Title { get { return title; } } } class Album { Photo []photo; public Album(int capacity) { photo=new Photo[capacity]; } public Photo this[int Index]//带有int参数的索引 { get { if(Index<0||Index>=photo.Length) { Console.WriteLine("索引无效"); return null; } return photo[Index]; } set { if(Index<0||Index>=photo.Length) { Console.WriteLine("索引无效"); return; } photo[Index]=value; } } public Photo this[string str] { get { foreach(Photo p in photo) { if(p.Title==str) return p; } Console.WriteLine("未找到"); return null; } } } }
相关文章推荐
- C,C#,C++中&&和||,&和|的联系和区别
- C#里结构与C/C++结构的区别加疑惑
- struct 与class的区别 C#与C++的区别
- C++内存管理(可以参考C++与C#区别文章的后面部分)
- C++和C#构造函数的区别
- c、c++和c#整体区别
- C++与C#的一些区别
- C#与C++对比学习1:基本语法区别
- Java C# .net 和 C C++ 跨平台的区别
- c#中using-添加引用-程序集(详解) 以及与 c++中include等区别
- Java、C#、C++定义数组区别
- C,C#,C++中&&和||,&和|的联系和区别
- Java;C#/C++与Delphi/C++Builder之区别与联系
- 总结一下C++与C#之间的区别
- c++中的隐藏与java、c#的区别
- c#学习之与c++的语法区别总结
- C++的类与C#的类的区别
- 浅谈C++和C#的区别&C#与.NET的关系
- java、C#以及C++中&&和||,&和|的联系和区别
- C++与C#之间的区别