(2)C#基础知识_类型与函数参数

1. 预定义类型和用户定义类型

1)预定义类型

   C#提供16种预定义类型,如下图所示。

    tips:

  • 与C++不一样,数值类型不具有布尔类型,如C++ 可以int a= 3,可以if(a)..;C#不行。
  • dynamic类型在动态语言中使用,使用dynamic可以自定义添加不存在的属性和值,编译不会对它进行类型检查。var与之不同,对于var,编译器会自动为其替换对应类型。

 2)用户定义类型

   c#提供了6种用户定义类型:class,struct,array,enum,delegate,interface.

2. 值类型、引用类型,值参数,引用参数

1)堆和栈

   介绍值参数和引用参数前,先介绍堆和栈的概念。堆和栈是指运行程序时,使用的存储数据的两个内存区域。栈是一个内存数组,遵循LIFO(后进先出)的数据结构,栈一般存储如下数据:

  • 某些类型变量的值;
  • 程序当前的执行环境
  • 传递给方法的参数

  栈的示意图如下:

 堆也是一块内存区域,它相当于栈很大,一般用于存储大型数据,堆内数据能以任意顺序存入和删除。
 堆的示意图如下:

2)值类型和引用类型

值类型:存储在栈上;
引用类型:类似于C++的指针,引用存储在栈上,实际数据存储在堆上。

C#的值类型和引用类型分类如下图:

tips:

  • 对于值类型,它也有可能在堆上。如在类中(引用类型)定义了值类型,那么在类实例中,该值类型数据,还是在堆中,如下图(MyType类中定义了一个值类型A):
  • 值类型都是struct,都继承于System.ValueType类,CLR对System.ValueType的派生类做了特殊处理,如使它内存分配方面具有值类型的特征,使其不能被继承(私有)等。

3)值参数和引用参数

    值参数:在方法调用时,在栈上先为形参分配空间,然后将实参的值复制给形参。
    引用参数:类似于C++的引用,在方法调用的时候,不会在内存中分配空间,只会为实参分配一个别名。

tips:

  • 引用参数声明和调用时必须都使用ref。
  • 引用参数的实参必须是变量,且用做实参时必须被赋值(防止未被赋值时,报错,相对于C++的改进),COM编码时调用时可省略ref,需传一个值(非变量)。
  • string比较特殊,虽然是引用类型,但作为值参传入函数时,string类型的变量在被赋予新值的时候,不会将原值擦去而填上新的值,而是会在堆中重新开辟空间,在空间中放入新的值,从而变量的地址也会改变,变成新空间的地址。(相当于把指针的值重新复制了,其他引用类型赋值操作也是一样的道理)

3. 枚举类型enum

枚举,其主要特性如下:

  • 枚举就像int一样,不过它“枚举”出了所有可能的值!
  • [Flags]特性可以使位标志枚举的tostring()方法提供更多格式化信息,如下形式:

4.委托和事件

1)委托

   我们先从字面上理解委托,就是将事情托付给别人做,而非自己亲自做,自己只负责通知。宏观上来看,委托就是一种通知机制,通知者需要做某事时,发起通知(Invoke),委托列表的订阅者得到通知,委托列表中的方法被顺序执行。委托还可以理解成一种容器,容器里放的是函数方法。

       

(1)可以使用+=,=,-=往委托容器里添加或移除方法。

(2)使用fun.invoke(a,b)或fun(a,b)触发委托,会将容器里的所有方法调用一遍。

(3)为什么要用委托:比如,在A类中实例化了B类,那A类中可以B类的数据,但B类却拿不到A类的数据,这时就需要在B类中声明一个委托,然后在A类中注册,这样B类委托被执行时,就可以拿到A类的数据了。

2)事件

   委托和事件的关系,类似于 字段和属性的关系。事件内部封装了一个委托,并对其进行了一些访问限制。

                            
(1)限制1:事件只能在定义类中Invoke;
         例如:在B类定义委托,因为需在其他类中注册,通常将委托定义成public的,那么在其他类中,就可以调用委托的Invoke,这样就"冒充通知”,因为B才是真正的通知者。这在某些严格场景下是被允许的,那么此时使用事件就可以解决这个问题。

(2)限制2:事件只能用+=,-=注册或移除方法列表;
        委托可以使用=来注册方法,这样之前注册的方法将被覆盖,可能会导致问题。事件则杜绝了这种错误。

事件的代码示例:

5. 匿名方法和lambda表达式

1)匿名方法

   对委托或事件赋值函数时,有的函数只会在此使用一次,为了简化,可以使用匿名方法。如下图:

匿名方法需要注意以下几点

   (1)匿名方法不会显式声明返回类型,返回值的类型必须和委托返回类型一致。

   (2)如果委托的参数不包括out参数,而且匿名方法没有使用任何参数,那么匿名可以将参数列表省略。如下:

              

   (3)匿名方法相关的变量作用域:

                

2)lambda表达式

   lambda是一种简化的匿名方法,也是对委托或事件赋值函数时使用!lambda表达式的形式如下:

代码实例:

      

6.可空类型

   某些情况下,你希望表示变量目前未保存有效值,对于引用类型可以用null表示,对于值类型,可以在定义时再类型后加上?,就也可以null表示未保存有效值;

int? a = null;

Nullable<int> a = null;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值