【C#小知识】C#中一些易混淆概念总结---------数据类型存储,方法调用,out和ref参数的使用
这几天一直在复习C#基础知识,过程中也发现了自己以前理解不清楚和混淆的概念。现在给大家分享出来我的笔记:
一,.NET平台的重要组成部分都是有哪些
1)FCL (所谓的.NET框架类库)
这些类是微软事先定义好的。
例如当我们新创建一个windows窗体应用程序是,VS会帮我们自动生成下面的代码:
using System;
using System.Collections.Generic;
using System.Text;
这些就是微软事先为程序员定义好的类库。程序员可以直接使用的。
2)CLR (所谓的公共语言运行时)
创建部署.NET程序的必备环境
使用C#,F#,VB等语言都可以来创建.NET应用程序。这时候就需要一个公共语言规范,来把不同的语言解释成.NET FramWork认识的东西。
二,什么是程序集
程序集主要有MSIL组成(所谓的微软中间语言,主要由dll文件组成)
不同编程语言程序被.NET FrameWork编译成程序集(dll文件),当程序需要被执行时,通过CLR中的JIT(及时编译器)编译成本地代码,并将指令发送给CPU执行。
程序集一般有两种:.dll和.exe文件(但是不是所有的dll和exe都叫程序集)
比如:我们在同一个解决方案下,建立多个应用程序或者类库文件。这些程序或者类库编译后就会变成不同的程序集。他们之间是相互独立的。之间如果想要相互访问,需要添加引用。
三,Parse转换和Convert转换的区别
1)Parse转换
①Parse转换只能转换字符串
②自变量是指定的数据类型才可以转换成功
下面的是.NET Reflector编译的源代码
2)Convert转换
①可以转换其他类型(如:类)
②与Parse的区别就是,转换前会对被转换的对象进行判断,如果对象为null则会转换失败
下面是实例源代码:
class Program
{
static void Main(string[] args)
{
string a = Console.ReadLine();
//Parse只可以转换字符串
int b = Int32.Parse(a); //Convert可以转换类等对象
ParseNumber parNum = new ParseNumber();
//这种写法编译器会报错
//int b = Int32.Parse(parNum);
int c = Convert.ToInt32(parNum); Console.WriteLine(b);
Console.WriteLine(b.GetType()); Console.ReadKey();
}
} class ParseNumber
{
private int nunm;
public int Num { get; set; }
}
四,数据类型的存储位置
1)存储在栈中的数据类型
所有数值类型,char,bool,枚举,结构体
2)存储在堆中
string,数组,类
管这些类型,他们的变量的声明都是保存在栈里,真实的对象保存在堆里面,栈里面的变量存储打的是对象的地址。
下面以数组来简单说一下这个问题:
//声明一个一维数组
int[] arr = new int[];
那么这个表达式的执行顺序是什么呢?
①首先程序会在栈中开辟一段名为arr的int[]类型的空间
②然后在堆中开辟一个int[]对象,再该对象中会有4块连续的内存空间
③堆中的对象返回类型为地址,即new int[4]表达式返回的是地址
示意图如下:
五,C#方法调用
1)在C#中我们可以给参数传递默认值,所以当我们调用这个方法的时候,可以不给这个参数传递值
static void Main(string[] args)
{
//声明一个一维数组
int[] arr = new int[];
Program pro = new Program();
//直接调用,没有传递参数值
pro.para(); }
public void para(int i=)
{
Console.WriteLine(i);
Console.ReadKey();
}
2)带默认参数的方法,默认值必须放在最右侧
下面的写法编译器会报错
3)方法的可变参数
①可变参数被Params
②Params只能用来修饰一维数组
static void Main(string[] args)
{
//声明一个一维数组
int[] arr = new int[]; for (int i = ; i < arr.Length; i++)
{
arr[i] = i;
}
Program pro = new Program();
pro.para();
//传递一位数组arr
pro.param(arr); Console.ReadKey();
}
//params用来修饰一维数组
public void param(params int[] arr)
{
foreach (var item in arr)
{
Console.WriteLine(item);
}
}
③给可变参数赋值的时候可以直接传递数组元素
//声明一个一维数组
int[] arr = new int[]; for (int i = ; i < arr.Length; i++)
{
arr[i] = i;
}
Program pro = new Program();
pro.para();
//传递一位数组arr
pro.param(arr);
//直接传递数组元素,调用时会自动将这些数封装成数组,并将数组传递
pro.param(, , , ); Console.ReadKey();
④与默认参数一样,可变参数的声明必须放在方法参数的最后
4)方法的out和ref参数
①out参数侧重于输出,必须在方法内对其赋值
如下图的声明编译器会报错
正确的使用方法
static void Main(string[] args)
{
//声明参数m
int m=;
Program pro = new Program();
//传递参数m,必须带有out参数标识
pro.outPara( out m);
Console.WriteLine(m);
Console.ReadKey();
} //out参数侧重于输出,必须在方法内对其赋值
public void outPara(out int i)
{
//方法内部必须对out参数进行赋值
i=;
}
②ref参数侧重于修改,但是也可以不修改参数的值
static void Main(string[] args)
{
//声明参数m
int m=;
Program pro = new Program();
//传递参数m,必须带有out参数标识
pro.outPara( out m);
//ref参数传递之前必须对其赋值,因为在方法内部可能会用到该参数
pro.refPara(ref m);
//Console.WriteLine(m);
Console.ReadKey();
} //
public void refPara(ref int i)
{
Console.WriteLine("可以不对参数i进行任何操作!");
}
输出结果如下:
六,属性易混淆点辨别
①属性本身不存值,值是存在这个属性所封装的字段里面
class Study
{
private int nID; //属性的值存储在封装的字段里面
public int NID
{ get { return nID; }
//这里我们给属性赋值
set { nID = value; }
}
}
通过访问属性字段获取字段的值
Study stu = new Study();
//通过访问属性字段获取字段的值
int nID = stu.NID;
②属性的返回值类型和字段的值类型没有关系
//属性的值类型为bool
private bool gender;
//字段的返回类型为string
public string Gender
{
get{return gender==true?"男":"女";}
set{gender =value=="男"?true:false;}
}
属性的返回值类型决定了get返回值的类型和set参数的类型
//属性的值类型为bool
private bool gender;
//字段的返回类型为string
public string Gender
{
//get的返回值类型为bool
get{return gender==true?"男":"女";}
//set参数类型为bool
set{gender =value=="男"?true:false;}
}
③自动属性到底是怎么回事?
看如下的代码:
private string strName;
//自动属性封装strName
public string StrName
{
get;
set;
}
这就是所谓的自动属性封装字段。在非自动属性中,程序默认的会有value值来给字段赋值,但是在自动属性中是怎么赋值的呢?
我们使用.NET Reflector反编译来看源代码:
这是我们封转的属性代码:
反编译set函数源代码:
我们可以看到.NET会默认为我们的程序生成一个成员变量<StrName>k__BackingField
get函数的源代码:
返回的也是该成员变量;
那么什么时候可以使用自动属性呢?
如果对一个字段取值和赋值的时候没有任何逻辑验证并且可读可写的时候,就可以使用自动属性。
七,C#类声明易混淆知识点
①首先给大家说明一个问题就是,文件名和类名必须是一样的么(就是我们在创建类的时候要命明,这个时候会默认的生成一样的类名称)?
如图所示
这个是必须的么?
我们尝试修改类名称为ChildName,然后访问类
可以看到我们要访问类,需要通过类名称访问而与文件名没有关系。
②类表达式的执行顺序和其意义
Study stu = new Study();
编译器执行代码的时候,
首先会先在栈中开辟一块类型为Study的内存空间放置变量stu
然后在堆中创建该变量的对象
然后调用该对象的构造函数,并且返回该对象在堆中的地址。
好吧,到这里,这次的分享就到此结束了。大家如果阅读的过程中有什么问题,可以跟我留言交流。
【C#小知识】C#中一些易混淆概念总结---------数据类型存储,方法调用,out和ref参数的使用的更多相关文章
- 【C#小知识】C#中一些易混淆概念总结(七)---------解析抽象类,抽象方法
目录: [C#小知识]C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用 [C#小知识]C#中一些易混淆概念总结(二)--------构造函数,this关键字 ...
- 【C#小知识】C#中一些易混淆概念总结(六)---------解析里氏替换原则,虚方法 分类: C# 2014-02-08 01:53 1826人阅读 评论(0) 收藏
目录: [C#小知识]C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用 [C#小知识]C#中一些易混淆概念总结(二)--------构造函数,this关键字 ...
- 【C#小知识】C#中一些易混淆概念总结(五)---------继承 分类: C# 2014-02-06 22:05 1106人阅读 评论(0) 收藏
目录: [C#小知识]C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用 [C#小知识]C#中一些易混淆概念总结(二)--------构造函数,this关键字 ...
- 【C#小知识】C#中一些易混淆概念总结(五)---------深入解析C#继承
目录: [C#小知识]C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用 [C#小知识]C#中一些易混淆概念总结(二)--------构造函数,this关键字 ...
- 【C#小知识】C#中一些易混淆概念总结(二)--------构造函数,this关键字,部分类,枚举 分类: C# 2014-02-03 01:24 1576人阅读 评论(0) 收藏
目录: [C#小知识]C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用 继上篇对一些C#概念问题进行细节的剖析以后,收获颇多.以前,读书的时候,一句话一掠而 ...
- 【C#小知识】C#中一些易混淆概念总结(四)---------解析Console.WriteLine() 分类: C# 2014-02-05 17:18 1060人阅读 评论(0) 收藏
目录: [C#小知识]C#中一些易混淆概念总结 [C#小知识]C#中一些易混淆概念总结(二) [C#小知识]C#中一些易混淆概念总结(三) ------------------------------ ...
- 【C#小知识】C#中一些易混淆概念总结(三)---------结构,GC,静态成员,静态类
目录: [C#小知识]C#中一些易混淆概念总结 [C#小知识]C#中一些易混淆概念总结(二) ---------------------------------------分割线----------- ...
- C#中一些易混淆概念总结
C#中一些易混淆概念 这几天一直在复习C#基础知识,过程中也发现了自己以前理解不清楚和混淆的概念.现在给大家分享出来我的笔记: 一,.NET平台的重要组成部分都是有哪些 1)FCL (所谓的.NET框 ...
- 【C#小知识】C#中一些易混淆概念总结(八)---------解析接口 分类: C# 2014-02-18 00:09 2336人阅读 评论(4) 收藏
这一篇主要来解析关于面向对象中最总要的一个概念--接口. 对于接口来说,C#是有规定使用Interface关键字来声明接口.它的声明是和类一致的.可以说接口就是一个特殊的抽象类.如下代码: cl ...
随机推荐
- spring p 标签
需要引入命名空间 xmlns:p="http://www.springframework.org/schema/p" p 是什么含义 p 是 property 的缩写,为了简化be ...
- Gridview的RowDataBound事件可以做很多事情
protected void gvTest_RowDataBound(object sender, GridViewRowEventArgs e) { //如果是绑 ...
- 通过hbase实现日志的转存(MR AnalyserLogDataRunner和AnalyserLogDataMapper)
操作代码(提前启动集群(start-all.sh).zookeeper(zkServer.sh start).启动历史任务服务器(mr-jobhistory-daemon.sh start histo ...
- hdu 5064 满足b2−b1≤b3−b2... 的最长子序列
http://acm.hdu.edu.cn/showproblem.php?pid=5064 要找出一个数组中满足b2−b1≤b3−b2≤⋯≤bt−bt−1 的最大的t 直接引题解: 1003 Fin ...
- 搜狗Q3业绩迅猛增长,战略整合稳步推进
继9月16日腾讯与搜狗战略结盟之后,最近搜狗再次吸引了业界关注的目光,10月29日,搜狗公布了截至2013年9月30日的第三季度未经审计的财务报告.财报显示,新搜狗Q3营收达5700万美元,同 ...
- 一句话为当前窗口客户区捉图: GetFormImage 来自万一的博客
一句话为当前窗口客户区捉图: GetFormImage http://www.cnblogs.com/del/archive/2008/10/24/1318738.html unit Unit1; i ...
- [leetcode] 20. Valid Sudoku
这道题目被放在的简单的类别里是有原因的,题目如下: Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. ...
- 【Win10】开发中的新特性及原有的变更(二)
声明:本文内容适用于 Visual Studio 2015 RC 及 Windows 10 10069 SDK 环境下,若以后有任何变更,请以新的特性为准. 十一.x:Bind 中使用强制转换 这点是 ...
- c# AOP编程:Context与方法拦截
之前做AgentBooking时候,遇到两个问题比较棘手,一个是异常的传递与捕获:如何可以合理地在层层代码调用中统一传递并统一捕获异常.因为如果有一个做法,可以地方统一处理异常,可以使代码减少很多tr ...
- WPF 最简单的TextBox水印
最简单的TextBox加水印的方法,但是不具有很强的通用性. 如果你只是使用一次,或者用的不多,偷偷懒可以使用. 因为此方法只需要修改TextBox的Template,而不用重写何任代码. 注意: 1 ...