30天C#基础巩固-----值类型/引用类型,泛型,空合并操作符(??),匿名方法

一:值类型/引用类型的区别

     值类型主要包括简单类型,枚举类型,和结构体类型等,值类型的实例通常被分配在线程堆栈上面变量保存的内容是实例数据本身。引用类型被分配在托管堆上,变量保存的是地址。引用类型主要包括类类型,接口类型,委托类型和字符串类型等。

关于参数传递,这里有四种:

       值类型参数的按值传递;

       引用类型参数按值传递;

关于string引用类型参数按值传递的特殊情况;虽然string类型也是引用类型,然而在按值传递时,传递的实参却不会因方法中形参的改变而被修改。

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("String引用类型按值传递的特殊情况");
            string str = "old string";         //引用类型
              ChangeStr(str);
            Console.WriteLine("调用之后的值:"+str);
            Console.ReadKey();
        }

        private static void ChangeStr(string oldStr)
        {
             oldStr = "New string";
            Console.WriteLine("方法中的oldStr:"+oldStr);
        }
    }

   造成这个原因是由于:string具有不变性,一旦一个string类型被赋值,则它是不会改变的,即不能通过代码来修改它的值,图中好像是对str进行了修改,但是由于string类型的不可变性,系统会重新分配一块内存空间来存放New string字符串。把修改的内存首地址赋值给oldStr变量,所以值就发生了变化。

       值类型参数的按引用传递;

       引用类型参数的按引用传递;

这里就需要使用到ref,out这两个关键字了,他们是把值类型和引用类型都按照引用进行传递。

二:重新认识------泛型

     泛型(generic):就是通用类型,它可以代替任意的数据类型,是类型参数化,从而达到只实现一个方法就可以操作多种数据类型的目的。泛型将方法实现行为和方法操作的数据类型分离,实现代码的重用。

            //用int作为实际参数来初始化泛型类型
              List<int> inList=new List<int>();
            inList.Add(3);
            //用string作为实际参数来初始化泛型类型
              List<string> inString=new List<string>();
            inString.Add("ahui");

上面的就是泛型,List<T>是.NET类库中实现的泛型类型,T是泛型参数(形参),想实例化一个泛型类型,就必须传入实际的类型参数。

    /// <summary>
    /// 定义一个泛型---比较各种类型的大小。 IComparable接口是因为里面有个CompareTo方法
    /// </summary>
    /// <typeparam name="T">泛型的参数,就是传递来的类型</typeparam>
    public class Compare<T> where T:IComparable
    {
        public static T CompareGeneric(T t1,T t2)
        {
            if (t1.CompareTo(t2)>0)
            {
                return t1;
            }
            else
            {
                return t2;
            }
        }
    }

这里面的T就是我们将来调用方法时往里面传递的类型(泛型的类型参数)。CompareGeneric是实现泛型的方法,代码中的where语句是类型参数的约束,它用来使类型参数可以适用于CompareTo方法。从而对类型参数进行约束。

            //调用泛型,直接点操作就可以来,只需要注意传递进去的类型就可以。
              Console.WriteLine(Compare<int>.CompareGeneric(1,2));
            Console.WriteLine(Compare<string>.CompareGeneric("2222","111"));
            Console.ReadKey();

   1:泛型除了可以实现代码的重用,还提供了更好的性能和类型安全特性。

   2:使用泛型可以减少装箱和拆箱带来的性能消耗。因为我们直接就是类型,不需要在将其转换为object类型再来进行操作。

   3:泛型代码中,T就是类型参数,无论调用类型方法还是初始化泛型实例,都需要用真实类型代替T。

   4:我们有的时候不需要给T赋值,编译器自己可以推测出T是什么类型的,这是类型参数的推断。(参数只能是一种类型)

   5:类型参数的约束:

共有4中约束,语法类似:约束要放在泛型方法或类型声明的末尾,并且要使用where关键字。

--->引用类型约束

      引用类型约束的表示形式为T:class,它确保传递的类型实参必须是引用类型。

    /// <summary>
    /// 引用类型约束
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class Samplereference<T>where T:Stream
    {
        public void Test(T stream)
        {
            stream.Close();
        }
    }

类型参数T设置了引用类型约束。where T:stream的意思就是告诉编译器,传递的类型必须是System.IO.Stream或者是其子类。

--->值类型约束

    表示形式:T:struct

    /// <summary>
    /// 值类型约束
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class Samplevaluetype<T> where T:struct             //约束为结构体了,(值类型)
    {
        public static T Test()
        {
            return new T();   //T是一个值类型,所有的值类型都有一个公共的无参构造函数,
        }
    }

--->构造函数类型约束

    表示形式:T:new(),若是有多个约束此约束应该最后指定。

--->转换类型约束

    表示形式:T:基类名。T:接口名或T:U;

---->组合约束

就是将上面的都组合在一起,类必须放在接口前面,不同的类型参数可以有不同的约束,但每种类型参数必须分别使用一个单独的where关键字。

三:可空类型

    可空类型也是值类型,但它包含null值的值类型,

    int? a=null;

int ?就是可空的int类型,?修饰符只是C#的语法糖,就是C#提供的一种方便的表示形式。

四:空合并操作符(??)

     ??操作符,它会对左右两个操作数进行判断,如果左边的数不为null,就返回左边的数。如果左边的数为Null,就返回右边的数。主要用于可空类型,也可以用于引用类型的判空,但是不能用于值类型。

        /// <summary>
        /// ??运算符
        /// </summary>
        private static void NullcoalescingOperator()
        {
            int? nullable = null;
            int? nullhasvalue = 1;

            int x = nullable ?? 12;            //和三目运算符功能一样。
            int y = nullhasvalue ?? 123;
            Console.WriteLine("可空类型没有值:"+x);
            Console.WriteLine("可空类型有值:" + y);

            Console.WriteLine();
            //??运于引用类型
            string stringnotnull = "123";
            string stringisnull = null;
            string result = stringnotnull ?? "456";
            string result2 = stringisnull ?? "12";
            Console.WriteLine("引用类型不为Null的情况:"+result);
            Console.WriteLine("引用类型为Null的情况:" + result2);
        }
        static void Main(string[] args)
        {
            Console.WriteLine();
            NullcoalescingOperator();
            Console.ReadKey();
        }

使用??运算符可以很方便地设置默认值,避免了通过if,else语句来进行判断,从而简化了代码行数,提高了代码的可读性。

五:匿名方法

解释:就是没有名字的方法,因为没有名字,匿名方法只能在函数定义(就是把方法的定义和实现嵌套在一起)的时候被用。其它任何 情况下都不能被调用。

委托是匿名函数的前提。

    public class Friend
    {
        /// <summary>
        /// 实现委托的方法(就是委托要传递的方法)
        /// </summary>
        /// <param name="nickName"></param>
        public void Vote(string nickName)
        {
            Console.WriteLine("昵称为:{0},来了呀",nickName);
        }
    }
    class Program
    {
        //定义委托
        private delegate void VoteDelegate(string name);

        private static void Main(string[] args)
        {
            //实例化委托对象
            VoteDelegate voteDelegate = new VoteDelegate(new Friend().Vote); //Vote方法当作了参数来传递。
            voteDelegate("ahui"); //把ahui传递到了下面的方法中。
            Console.ReadKey();
        }
    }

下面是使用匿名函数

   class Program
    {
        //定义委托
        private delegate void VoteDelegate(string name);

        private static void Main(string[] args)
        {
            //使用匿名函数来实例化委托。必须为delegate。其余就和方法的一样。
             VoteDelegate voteDelegate = delegate(string nickName)
            {
                Console.WriteLine("昵称为:" + nickName);
            };
            //通过调用委托来回调Vote()方法,这是隐式调用方式。
              voteDelegate("ahui");
            Console.ReadKey();
        }
    }

我们使用匿名函数就不需要单独定义一个Vote方法,这减少了代码行数。

匿名函数的缺点:  

           不能被其他地方调用,容易形成闭包。

时间: 2024-10-14 22:22:51

30天C#基础巩固-----值类型/引用类型,泛型,空合并操作符(??),匿名方法的相关文章

数往知来C#之接口 值类型与引用类型 静态非静态 异常处理 GC垃圾回收 值类型引用类型内存分配&lt;四&gt;

C# 基础接口篇 一.多态复习 使用个new来实现,使用virtual与override    -->new隐藏父类方法 根据当前类型,电泳对应的方法(成员)    -->override重写 无论什么情况,都是执行新的方法(成员) 继承是实现多态的一个前提,没有继承多态是不能实现的 父类与子类实现多态 抽象类与子类实现 抽象类不能实例化 抽象类中的抽象方法没有方法体 抽象类的成员有哪些   ->包含非抽象成员   ->不能实例化   ->子类必须实现父类的 抽象方法,除非子

6个重要的.NET概念:栈,堆,值类型,引用类型,装箱,拆箱

6个重要的.NET概念:栈,堆,值类型,引用类型,装箱,拆箱 引言 本篇文章主要介绍.NET中6个重要的概念:栈,堆,值类型,引用类型,装箱,拆箱.文章开始介绍当你声明一个变量时,编译器内部发生了什么,然后介绍两个重要的概念:栈和堆:最后介绍值类型和引用类型,并说明一些有关它们的重要原理. 最后通过一个简单的示例代码说明装箱拆箱带来的性能损耗. 声明变量的内部机制 在.NET程序中,当你声明一个变量,将在内存中分配一块内存.这块内存分为三部分:1,变量名:2,变量类型:3,变量值. 下图揭示了声

js:值类型/引用类型/内存回收/函数传值

把这4个概念放在一起写,因为它们是互通的 值类型:一个变量对应一块内存 var a=1; var b=a; a=2; 此时b还是等于1 就像你的克隆人,你心情不好去跳崖,他才不会傻乎乎地跟着你去跳 数值.boolean.null.undefined都是值类型 引用类型:有的博主这样比喻,一家店,它的引用就是它的钥匙 鉴于“作的精神”,我换一种比喻 一台电视机(内存)和它的遥控器关系(引用变量) 可以用遥控器换频道,但不可以用遥控器把电视变成冰箱 如果这电视不只一个遥控器,那么它们可以共同控制电视

C#基础之值类型和引用类型

值类型:int double char bool decimal struct enum     值存储在内存的栈上 引用类型: string 数组 自定义类 接口 委托  值存储在堆中 值传递:把值类型作为参数传递,传递的是值本身----注:ref可以把值传递改变为引用传递 引用传递:把引用类型的值作为参数传递,传递的是引用 static void Main(string[] args) { int number = 10; Test(number); Console.WriteLine(nu

C#基础:值类型、引用类型与ref关键字

在C#中,ref的意思是按引用传递.可以参考C++: int a = 10, b = 20; void swap(int x, int y) { int temp = x; x = y; y = temp; } 如果简单的调用这个swap,比如:swap(a, b),那么你根本没办法交换这两个变量的值,因为x和y都是形参,在swap返回的时候,x和y都被释放了.但如果是这样定义swap: void swap (int& x, int& y) { int temp = x; x = y; y

C#基础知识----值类型与引用类型

CLR支持两种基本类型:值类型和引用类型 那么又有哪些数据类型是值类型的   又有哪些数据类型是引用类型的呢?请看下面的简单归纳: 值类型: 所有的数值类型(long int short byte ulong uint ushort sbyte decimal double float) bool 枚举(enum) 结构(struct) 引用类型: string 数组 类(class) 接口(interface) 引用类型和值类型的划分依据:  他们在内存中的存储方式不同      内存最重要的

深入C#内存管理来分析值类型&amp;引用类型,装箱&amp;拆箱,堆栈几个概念组合之间的区别

C#初学者经常被问的几道辨析题,值类型与引用类型,装箱与拆箱,堆栈,这几个概念组合之间区别,看完此篇应该可以解惑. 俗话说,用思想编程的是文艺程序猿,用经验编程的是普通程序猿,用复制粘贴编程的是2B程序猿,开个玩笑^_^. 相信有过C#面试经历的人,对下面这句话一定不陌生: 值类型直接存储其值,引用类型存储对值的引用,值类型存在堆栈上,引用类型存储在托管堆上,值类型转为引用类型叫做装箱,引用类型转为值类型叫拆箱. 但仅仅背过这句话是不够的. C#程序员不必手工管理内存,但要编写高效的代码,就仍需

聚沙成塔【1】——值类型/引用类型

值类型 :顾名思义就是在内存中储存其值的类型,是存放于堆栈中的类型,13个{sbyte,byte,short,ushort,int,uint,long,ulong,float,double,decimal,bool,char} 引用类型   :在内存中存放的是对其的引用地址,是存放于托管堆中的类型,2个{string,object} -------------------------------------------------------------------------------- ☆

javascript基本数据类型与值类型引用类型说明

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 摘要:本文主要讲了javascript中的基本数据类型,以及值类型和引用类型的区别与使用 一.基本数据类型 在javascript中申明变量使用的关键字都是var,这点与其他的编程语言不尽相同,但是javascript亦含有五种基本的数据类型(也可以说是简单数据类型),它们分别是:Undefined,Null,Boolean,Number和String.还含有一种复杂数据类型-Object.