C#复习笔记(2)--C#1所搭建的核心基础

通过对C#1所搭建的核心基础的深入了解,可以知道之后的C#版本在C#1的基础上做了很多扩展,而这些扩展都是基于C#搭建的核心基础而来的。

委托

一、编写委托的过程

委托经常和C语言的“函数指针”挂钩。委托是方法参数化、函数式语言一个重要的表达方式。C#1中编写一个委托要经过四部:

1、声明委托类型

delegate void StringProcessor(string param1);

这个委托指定了一种无返回值,有一个string类型的参数的方法。

这个委托继承自System.MulticastDelegate,后者又派生自System.Delegate.

委托本身是引用类型,所以声明委托的时候不能在方法中声明。可以作为内部类,也可以声明到namaspace下面。

  2.、必须有一个方法包含了要执行的代码,这个方法要和委托声明的签名一致,包括参数和返回值

C#一中要为委托找到一个方法的话必须要和委托的签名完全一直,在C#2中允许委托的斜边和逆变。必须下面的委托:

delegate object SayHello(string word);  

这个委托可以被下面这个方法实例化:

 static string Sayhello(object word)
        {
            Console.WriteLine(word);
            return word.ToString();
        }

3、创建委托本身


可以采用new操作符来创建一个委托的实例:

 SayHello say = new SayHello(Sayhello);

C#2中支持委托-方法组的转换,所以,可以直接使用

SayHello say = Sayhello;

4、调用委托

一切准备就绪后就可以用invoke方法来完成调用。C#还可以更简单的完成这个操作,使用

SayHello say = Sayhello;
            say("hello,you");

就可以完成,不过在背后编译器帮你完成了一些工作:

 二、合并和删除委托


委托和string的特征有一些相似:都是不易变的。这体现在委托的合并和删除上面:

委托内部有一个操作列表(invocation list):System.Delegate的静态方法Combine和Remove负责创建新的委托实例。其中,Combine将两个委托的操作列表链接到一起,Remove负责将一个委托实例的一个操作删除。它们都不改变原有的类型(所以说和string很像)他们都是返回一个Delegate。

很少在代码中直接调用Delegate.Combine,Delegate.Remove而是用+=和-=操作符。这同样是编译器的功劳:

如果调用列表中抛出异常,那么抛出异常的那个方法导致调用列表不在执行。

如果有返回值,那么调用列表会返回最后调用的那个方法的值。所以一般不会在调用列表中执行有返回值的方法。

但是如果有必要,可以通过调用invocationlist来逐个执行方法并获取返回值。

三、事件

首先来看事件的声明:

public event SayHello SayHelloEvent;

事件是对委托的封装,有点儿类似于属性和后备字段的关系,上面这句声明编译器会做如下工作:

1、在相同的作用域中声明一个SayHello委托类型的私有字段

2、声明一个类似于属性的块结构,这个块结构包含一个类似于属性的取值方法和赋值方法,由编译器进行命名,前缀分别是"add"和"remove"。

3、在外部,会通过+=和-=来操作事件,声明事件时的访问修饰符会限制这一操作。就是说如果声明为一个private的事件的话外部是不能操作事件的。

4、在内部,+=操作符会调用“add”前缀的方法,“add”前缀的方法会调用Delegate.Combine来合并操作,同理,-=操作符会调用“remove”前缀的方法,该方法会调用Delegate.Remove来删除操作。

5、从上面可以看出,事件就是一对儿“add"和”remove“方法。他封装了委托,从而避免调用方直接操作委托,而是通过事件来间接的操作委托,在类的内部可以看到委托,在类外部可以看见事件。

总结一下,事件不是委托实例,只是成对儿出现的add/remove方法。类似与属性的get/set方法。

类型系统的特征

在C#4之前,C#的类型系统是静态的、显式的和安全的。

一、静态类型和动态类型

C#是静态类型的:每个变量或表达式的类型在编译时都是已知的。只有类型已知的操作才是被允许的。静态这个词用来表示使用不变的类型数据来分析哪些操作可用。

与静态类型想对应的是动态类型,动态类型的实质是变量中含有值,但那些值不限于特定的类型。所以编译器不能执行相同形式的检查。

二、显示类型和隐式类型

这个讨论只有在静态语言的环境中才是成立的。对于显式类型来说,每个变量都在声明时指定类型。隐式类型则允许编译器变量的用途来确定变量的类型。无论是显式还是隐式,表达式的类型都会在编译时就确定。

三、类型安全与类型不安全

C#是类型安全的,C#支持一些类型安全的转换:继承上的、数值上的,如果使用强制类型转换,编译器会检测转换的结果,也会抛出异常来组织程序的继续运行,C#还支持有限的协变和逆变(C#4)。但是和真正的协变和逆变还有很长一段距离。

可以通过显式实现接口来处理协变和逆变上的一些限制。

总结一下:

C# 1是静态类型的—— 编译器知道你能使用哪些成员;

C# 1是显式的—— 必须告诉编译器变量具有什么类型;

C# 1是安全的——除非存在真实的转换关系, 否则不能将一种类型当做另一种类型;

静态类型仍然不允许一个集合成为强类型的“ 字符串列表” 或者“ 整数列表”, 除非针对不同的元素使用大量的重复代码;

方法覆盖和接口实现不允许协变性/ 逆变性。

值类型和引用类型

一、值类型和引用类型的基础知识

对于引用类型的表达式(如一个变量),它的值是一个引用,而非对象。
    引用就像URL——是允许你访问真实信息的一小片数据。

对于值类型的表达式,它的值是实际的数据。

有时,值类型比引用类型更有效, 有时恰好相反。
    引用类型的对象总是在堆 上, 值类型的值既可能在栈 上, 也可能在堆上,具体取决于上下文。 
    引用类型作为方法参数使用时, 参数默认是以“值传递”方式来传递的—— 但值本身是一个引用。 

值类型和引用类型的本质区别在于复制的方式不同:值类型复制值本身,引用类型复制的是引用。

两种类型的另一个差异在于, 值类型不可以派生出其他类型。 这将导致的一个结果就是,值不需要额外的信息来描述值实际是什么类型。 把它同引用类型比较, 对于引用类型来说, 每个对象的开头都包含一个数据块, 它标识了对象的实际类型, 同时还提供了其他 一些信息。 永远都不能改变对象的类型——执行简单的强制类型转换时, 运行时会获取一个引用, 检查它引用的对象是不是目标类型的一个有效对象。如果有效, 就返回原始引用; 否则抛出异常。 引用本身并不知道对象的类型—— 所以同一个引用“ 值” 可用于( 引用) 不同类型的多个变量。 例如 下面 的 代码:

 Stream stream=new MemoryStream();
            MemoryStream memory = (MemoryStream) stream;//第1行创建一个新的MemoryStream对象, 并将stream变量的值设为对那个新对象的引用。 第2行检查stream的值引用的是不是一个MemoryStream( 或派生类型)对象,并将MemoryStream的值设为相同的值。

值类型变量本身存储的是值,引用类型变量本身存储的是引用,这个引用里面包含一个指向真正对象的地址。变量的值在它声明时的位置存储。局部变量的值总是存储在栈( stack)中(这个结论只有 在C#1中完全成立。以后会讲到,在更高版本C#中,在特定情况下,局部变量最终可能存储在堆中。)实例变量的值总是存储在实例本身存储的地方。 引用类型实例(对象)总是存储在堆( heap)中, 静态变量也是。

    按值传递和按引用传递的区别是按值传递的是副本,按引用传递的是别名。

    装箱的背景在于值类型和引用类型的值不同:值类型的值就是值本身,而引用类型的值只是一个引用。

    值类型的值会在需要引用类型的行为时被装箱; 拆箱则是相反的过程。

构建于C#1之上的新特性

一、与委托有关的新特性

C#1中的委托-->C#2的泛型、方法组转换、匿名方法、委托协变性和逆变性-->C#3的lambda表达式、内建的Func、Action、泛型的接口和委托的协变性和逆变性

二、与类型系统有关的特性

C#2-->泛型、委托的协变性和逆变性-->C#3匿名类型、隐式类型、扩展方法-->C#4受限的泛型协变性和逆变性、动态类型

三、与值类型有关的特性

C#2-->泛型、Nullable<t>可空值类型

原文地址:https://www.cnblogs.com/pangjianxin/p/8638609.html

时间: 2024-11-06 12:47:35

C#复习笔记(2)--C#1所搭建的核心基础的相关文章

001-C#1所搭建的核心基础

今天我们就要说两个东西:委托与值/引用类型. 1委托. 因为在unity中我们还是用的很少,所以这个委托我就一直不是很明白,所以今天就来说说这个委托到底是什么东西.我其实在unity中用的形式一般是这个样子的. btn.OnClick.AddListener(()=>{Debug.Log("Hello World")});这个形式是一个Lambda形式,但是在实际事情下还是用的很少,Unity有一点还是不好的,将大部分功能都封装给一个类,我们只需要调用API就行了,但是我们并不知

C#1所搭建的核心基础

一,委托 委托封装了包含特殊返回类型和一组参数的行为,类似包含单一方法接口. 委托类型声明中所描述的类型签名决定了哪个方法可以用于创建委托实例,同时决定了调用的签名:委托类型实际上只是参数类型的一个列表以及一个返回类型 创建委托实例,需要一个方法已经调用该方法的目标: void Invoke(string input)具有个委托相同的类型和相同的参数 委托实例不易变形: 委托是不易变的.委托实例就和string一样.Delegate.Combine和string.Concat很像,都是合并现有的

C# 1.0所搭建的核心基础

2.1委托 不需要直接指定一个要执行的行为,而是将这种行为用某种方式“包含”在一个对象中.这个对象可以像其他任何对象一样使用.在该对象中,可以执行封装的操作.可以将委托类型看作只定义了一个方法的接口,将委托实例看作实现了那个接口的对象. 类似遗嘱,遗嘱由一系列指令组成,比如:“付帐单,捐善款,其余财产留给猫”.去世后,律师会执行这些指令. C#中的委托和现实世界的遗嘱一样,也是要在恰当的时间执行一些列操作.如果代码想要执行操作,但不知道操作细节,一般可以使用委托.  

【深入理解C#】第2章 C#1所搭建的核心基础

1)委托类型 基本理解: 类型安全的函数指针. 可以间接完成某种操作,虽增加了复杂性,但也增加了灵活性. 可以看作方法的占位符. 为什么要用委托: 可以传递函数意味着可以将业务逻辑作为参数传递. 间接调用 想要执行某些操作,但无需知道操作细节(Thread类) 2)C#1的类型系统是静态的,显式的和安全的 静态--编译器知道你能使用哪些成员 显式--必须告诉编译器变量具有什么类型 安全--除非存在真实的转换关系,否则不能将一种类型当作另一种类型 值类型和引用类型 类(使用class声明)是引用类

安卓开发复习笔记——Fragment+FragmentTabHost组件(实现新浪微博底部菜单)

记得之前写过2篇关于底部菜单的实现,由于使用的是过时的TabHost类,虽然一样可以实现我们想要的效果,但作为学习,还是需要来了解下这个新引入类FragmentTabHost 之前2篇文章的链接: 安卓开发复习笔记——TabHost组件(一)(实现底部菜单导航) 安卓开发复习笔记——TabHost组件(二)(实现底部菜单导航) 关于Fragment类在之前的安卓开发复习笔记——Fragment+ViewPager组件(高仿微信界面)也介绍过,这里就不再重复阐述了. 国际惯例,先来张效果图: 下面

android笔记1——开发环境的搭建

Long Long ago...已经成为了历史,我还是要说出一个真相:早年前,那时候,android还不被大众所认知的时候,当然开发者也没不像现在那样趋于饱和状态.一位大牛前辈,也是我的学长,那时候我还在上大学.前辈告诫我有时间得去看看android开发,那时候的自己,年轻.冲动.不畏惧,毅然地选择了java服务端开发,放弃了学习android开发. 时隔数年的今天,因为公司业务项目的发展,我还是得去做android开发工作...虽然这几年间断断续续的看了些android开发,但是将成为历史的今

计算机图形学 复习笔记

计算机图形学 复习笔记 (个人整理,仅做复习用 :D,转载注明出处:http://blog.csdn.net/hcbbt/article/details/42779341) 第一章 计算机图形学综述 研究内容 图形的概念:计算机图形学的研究对象 能在人的视觉系统中产生视觉印象的客观对象 包括自然景物.拍摄到的图片.用数学方法描述的图形等等 图形的要素 几何要素:刻画对象的轮廓.形状等 非几何要素:刻画对象的颜色.材质等 图形表示法 点阵表示 枚举出图形中所有的点,简称为图像. 参数表示 由图形的

安卓开发复习笔记——Fragment+ViewPager组件(高仿微信界面)

什么是ViewPager? 关于ViewPager的介绍和使用,在之前我写过一篇相关的文章<安卓开发复习笔记——ViewPager组件(仿微信引导界面)>,不清楚的朋友可以看看,这里就不再重复. 什么是Fragment? Fragment是Android3.0后新增的概念,Fragment名为碎片,不过却和Activity十分相似,具有自己的生命周期,它是用来描述一些行为或一部分用户界面在一个Activity中,我们可以合并多个Fragment在一个单独的activity中建立多个UI面板,或

安卓开发复习笔记——WebView组件

我们专业方向本是JAVA Web,这学期突然来了个手机App开发的课设,对于安卓这块,之前自学过一段时间,有些东西太久没用已经淡忘了 准备随笔记录些复习笔记,也当做温故知新吧~ 1.什么是WebView? WebView(网络视图)能加载显示网页,可以将其视为一个浏览器,它使用了WebKit渲染引擎加载显示网页. 废话不多说,直接上代码 1.需要在xml布局文件中声明WebView组件 1 <WebView 2 android:id="@+id/webview" 3 androi