LINQ学习(二):正式学习LINQ前必须了解的C#语言特性--上篇

在正式学习LINQ之前,我们必须掌握的几个重要的C#语言特性
1、隐式类型
2、匿名类型
3、自动属性
4、初始化器
5、委托
6、泛型
7、泛型委托
8、匿名方法
9、Lambda表达式
10、拓展方法
11、迭代器
以上特性均了解,可忽略此文,开始正式的接触LINQ

一、隐式类型
1、为什么要使用隐式类型?
    我们在声明一个变量的时候,总是要为一个变量指定它的类型,甚至在foreach一个集合时也要为遍历的元素指定变量的类型,隐式类型的出现,苦逼的码农就不需要再做这个工作了!
2、使用方法
            var i = 1;//int i=1;
            var j = "123";//string j="123";
            var obj = new object();//object obj=new object();
上面的每一行代码,与代码后的注释,作用是完全一样
你可能会问,var会降低性能吗?
    var并不会降低性能,因为var声明的变量与注释中声明变量的方法,编译后产生的中间语言代码(IL码)是完全一样!
 3、注意事项:
    我们在使用var关键字声明一个变量时,不能只声明而不给它赋值,如果不赋值,编译器就无法推导出咱们声明的变量是什么类型。

二、匿名类型
1、为什么要使用匿名类型?
    创建一个对象的时候,咱们不想定义这个对象的类型时,可以使用匿名类型。
2、使用方法
            //实例化对象
            var myObj = new
            {
                Guid.Empty
                ,myTitle = "匿名类型"
                ,myOtherParam = new int[] { 1, 2, 3, 4 }
            };
            Console.WriteLine(myObj.Empty);//另一个对象的属性名字,被原封不动的拷贝到匿名对象中来了。
            Console.WriteLine(myObj.myTitle);
            Console.ReadKey();
new关键字之后,我们直接开始定义对象的属性,并且为定义的属性赋值。
对象实例化之后,在创建对象的方法中,我们可以访问对象的属性。
所以,在把一个对象的属性拷贝到匿名对象中时,可以不用显示的指定对象的属性名,原属性的名字会自动拷贝到匿名对象中
3、注意事项
匿名对象myObj的类型是属于Anonymous Type类型
不要试图在创建匿名对象的方法外面去访问对象的属性
三、自动属性
1、为什么要使用自动属性?
    当我们为一个类定义属性时,我们一般都需要先声明字段,再声明属性,然后通过属性来访问字段。这样无非是非常麻烦的一件事情。
比如:
        private string id;
        private string name;
        public string Id
        {
            get { return id; }
            set { id = value; }
        }
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
尤其是当我们对象关系映射中的实体类,这些私有变量对我们一点用处也没有,只会增加我们的代码量,给我们码农增加烦恼
我们就开始使用自动属性
2、使用方法:

        public string Id { get; set; }
        public string Name { get; set; }

自动属性的特性与var隐式类型一样,编译器帮我们做了工作,不会影响性能。

四、初始化器

1、为什么要使用初始化器?
当我们创建一个对象并给对象赋值时,一般这样写:
            var t = new Test();
            t.Id = "IdCard";
            t.Name = "kevin";

使用初始化器之后,可以这样写:

            var t = new Test
            {
                Id = "IdCard",
                Name = "kevin"
            };

2、使用方法:

            //初始化器赋值
            var objOne = new Test()
            {
                Id = "IdCard",
                Name = "kevin"
            };
            //构造函数+初始化器赋值
            var objTwo = new Test("IdCard")
            {
                Name = "kevin"
            };
            //集合初始化
            var arr = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8 };
    怎样编写代码因人而异,每个人有每个人的编码习惯。我所在的开发环境为VS2017,若是不使用初始化器,VS2017就警告提醒。。。这可能代表了Microsoft在做一个编码规范的统一。

五、委托
1、为什么要使用委托?
    引入委托后,编程人员可以把方法的引用封装在委托对象中(把过程的调用转化为对象的调用,充分体现了委托加强了面向对象编程的思想。),然后把委托对象传递给需要引用方法的代码,这样在编译的过程中我们并不知道调用了哪个方法,这样一来,C#引入委托机制后,使得方法声明和方法实现的分离,充分体现了面向对象的编程思想。
2、使用方法:
首先我们来看一个简单的委托实现
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DelegateTest
{
    class Program
    {
        //定义一个委托类型
        //输入int型参数,返回Boolean类型的值
        delegate Boolean moreOrLessDelgate(int item);
        static void Main(string[] args)
        {
            //定义数组
            var arr = new List<int> { 5, 2, 0, 66, 4, 32, 7, 1 };
            //创建moreOrLessDelgate委托实例,输入的参数为方法名
            var delgateMore = new moreOrLessDelgate(More);
            var delgateLess = new moreOrLessDelgate(Less);
            Console.WriteLine("----------------More-------------");
            Print(arr, delgateMore);
            Console.WriteLine("----------------Less-------------");
            Print(arr, delgateLess);
            Console.ReadKey();
        }
        static void Print(List<int> arr, moreOrLessDelgate delgate)
        {
            foreach (var item in arr)
            {
                if (delgate(item))
                {
                    Console.WriteLine(item);
                }
            }
        }
        /// <summary>
        /// 判断参数是否大于10
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        static bool More(int item)
        {
            if (item > 10)
            {
                return true;
            }
            return false;
        }
        /// <summary>
        /// 判断参数是否小于10
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        static bool Less(int item)
        {
            if (item < 10)
            {
                return true;
            }
            return false;
        }
    }
}

看完代码后,我们发现:
    (1)、首先定义一个委托类型
        delegate Boolean moreOrLessDelgate(int item);

        委托与类,是同一个级别,其实:委托就是一种类型,delegate与class标志的类型不一样,这种moreOrLessDelgate这种类型代表某一类方法。所以也可以在前面加public之类的修饰符

    (2)、既然有类型,那么就会有类型的实例。
         委托类型的实例化方式与类的实例化方式相似,都可以通过关键字new来进行实例化。

          var delgateMore = new moreOrLessDelgate(More);
          var delgateLess = new moreOrLessDelgate(Less);
            他们输入的参数,就是方法。

    (3)、有了类型的实例,那么就会有操作类型实例的代码
            Print(arr, delgateMore);
            Print(arr, delgateLess);
            我们把前面两个实例传递给Print方法,实现实例的操作。
    

六、泛型
1、为什么要使用泛型?

    有了泛型之后,可以加强我们代码的重用性的同时,还避免了装箱、拆箱的性能损耗。

    可以点击查看我这篇博文--泛型的理解,对泛型进行一个详细了解

2、使用方法

    由于泛型内容实在是过多,加上本文篇幅有限,在此不做过多介绍。有兴趣的同学可以点击查看泛型详解

七、泛型委托
1、为什么要使用泛型委托?

    委托需要定义delgate类型,使用起来颇多不便,而且委托本就代表某一类方法,开发经常使用的委托基本可以总结为三类,哪三类呢?

    第一类:Predicate--传入一个T类型的参数,并且需要返回一个bool类型的返回值

    第二类:Action--传入参数可以有0~16个,但是没有返回值

    第三类:Func--为了弥补Action不能有返回值而存在。传入参数可以有0~16个,必须要有一个返回值,返回值的类型由使用者确定。

有了这三类泛型委托,我们编码效率又提高了不少。

2、使用方法:

<1>Predicate

可以将我们上述创建moreOrLessDelgate委托实例的语句改成如下所示:

            //原:var delgateMore = new moreOrLessDelgate(More);
            var delgateMore =new Predicate<int>(More);
            //原:var delgateLess = new moreOrLessDelgate(Less);
            var delgateLess = new Predicate<int>(Less);

按照上述方式更改了创建委托实例的语句后,发现操作委托实例的方法Print()出现编译错误 ,如下图所示:


原来是因为我们传入的委托实例,并不是Predicate<int>类型,而是moreOrLessDelgate

所以我们应该把Print方法的声明改为如下所示:

        //原:static void Print(List<int> arr, moreOrLessDelgate delgate)
        static void Print(List<int> arr, Predicate<int> delgate)

我们按F12进入Predicate<int>类型的定义查看,结果如下所示:

namespace System
{
    //
    // 摘要:
    //     表示一种方法,该方法定义一组条件并确定指定对象是否符合这些条件。
    //
    // 参数:
    //   obj:
    //     要针对此委托所表示的方法中定义的条件进行比较的对象。
    //
    // 类型参数:
    //   T:
    //     要比较的对象的类型。
    //
    // 返回结果:
    //     true如果obj满足此委托; 所表示的方法中定义的条件否则为false。
    public delegate bool Predicate<in T>(T obj);
}

看完定义我们发现,原来是.net为我们定义了一个委托。与我们开始定义的委托相比:

 public delegate Boolean moreOrLessDelgate(int item);
.net给我们提供的委托支持任意类型的参数!


<2>Action

Action委托代表:可以有0~16个输入参数,输入参数类型不确定,但没有返回值这一类的方法,

我们先定义2组方法:

        static void ActionOne()
        {
            Console.WriteLine("ActionOne");
        }
        static void ActionTwo(int a,string b,double c)
        {
            Console.WriteLine("ActionTwo");
        }

我们再对委托进行实例化操作:

            var actionOne = new Action(ActionOne);
            var actionTwo = new Action<int,string,double>(ActionTwo);
<3>Func

为了弥补Action泛型委托没有返回值的不足,.net对此体提供了Func泛型委托

与Action对比,相同的时Func也是最多0~16个输入参数,参数类型由使用者确定

不同的是,Func规定必须要有一个返回值,返回值的类型也是由使用者确定

那我们再创建2个方法测试一下:

        static string FuncOne()
        {
            return "FuncOne";
        }
        static string FuncTwo(int a, string b, double c)
        {
            return "FuncTwo";
        }

注意:当我们对Func委托进行实例化操作时,与Action稍有不同

            var funcOne = new Func<string>(FuncOne);
            var funcTwo = new Func<int,string,double,string>(FuncTwo);

Func的类型“<>”中,最后一个泛型参数类型,代表着返回值类型。


本打算把剩下的四个语言特性也在本篇总结完,但是一次性全写完,篇幅未免太过冗长,可若是一笔带过,未免也太过草率。

猜你喜欢

转载自blog.csdn.net/AdolphKevin/article/details/81055639