点点滴滴C#-001-匿名类型和var

C#匿名类型和var

官方文档: https://msdn.microsoft.com/zh-cn/library/bb397696.aspx

https://msdn.microsoft.com/zh-cn/library/bb383973.aspx

https://msdn.microsoft.com/zh-cn/library/bb384061.aspx

https://msdn.microsoft.com/zh-cn/library/bb384090.aspx

 

匿名类

匿名类型提供了一种方便的方法,可用来将一组只读属性封装到单个对象中,而无需首先显式定义一个类型。类型名由编译器生成,并且不能在源代码级使用。每个属性的类型由编译器推断。可通过使用 new 运算符和对象初始值创建匿名类型

说白了,匿名类型就是当你需要使用一种类型结构时,不必显示的定义就可以使用。虽然你没有定义但是编译器会为你自动创建一种类型。

例如

var stuff = new { Name = "wang", Age = 30 };

            Console.WriteLine(stuff.Name+ " : " + stuff.Age);

我们并没有定义类,但是上述代码可以正常运行。实际上运行上述代码编译器会为我们创建一个类型。上述代码大约等同于

public class Stuff

        {

            public string Name { get; private set; }

 

            public int Age { get; private set; }

 

            public Stuff(string name, int age)

            {

                this.Name = name;

                this.Age = age;

            }

        }

 

var stuff = new Stuff("wang", 30);

            Console.WriteLine(stuff.Name+ " : " + stuff.Age);

这里要注意匿名类型的属性都是只读类型的。也就是说匿名类型生成后,属性时不能改动的

例如

var stuff = new { Name = "wang", Age = 30 };

            stuff.Age = 20;

            Console.WriteLine(stuff.Name+ " : " + stuff.Age);

第二行代码会报错。

还有一种创建匿名类的方式

string Name = "wang";

            int Age = 30;

            var stuff = new { Name, Age };

            Console.WriteLine(stuff.Name+ " : " + stuff.Age);

这里并没有指定匿名类的属性名,编译器会为匿名类型成员指定与用于初始化这些成员的属性相同的名称,但是如果是表达式则必须显示指定属性名。

例如

string Name = "wang";

            int Age = 30;

            var stuff = new { Name, Age,IsOlder = (Age >= 30)};

            Console.WriteLine(stuff.Name+ " : " + stuff.Age + " " + stuff.IsOlder);

通常我们不会像上面那样使用具体的变量创建匿名类,使用对象属性的情况会更多。

比如我们定义了一个Stuff类,他有很多属性

public class Stuff

        {

            public string Name { get; set; }

 

            public int Age { get; set; }

 

            public int ID { get; set; }

 

            public double Salary { get; set; }

        }

 

我们有一个Stuff的集合

Stuff[] arrStuffs = new Stuff[100];

如果我们想从集合中检索年龄不小于30岁的员工,并且我们只需要知道姓名和年龄即可,其它的信息我们不关心,则可以使用下面的语句

            var olders = from stuff in arrStuffs

                         where stuff.Age >= 30

                         select new { stuff.Name,stuff.Age };

我们可以看到匿名类部分并没有指定具体的属性,则Name和Age就成为我们匿名类的属性名。

这里还需要说明几点

1>  匿名类型是直接从对象派生的类型,并且其无法强制转换为除对象外的任意类型

2>  如果程序集中的两个或多个匿名对象初始值指定了属性序列,这些属性采用相同顺序且具有相同的名称和类型,则编译器将对象视为相同类型的实例。它们共享同一编译器生成的类型信息。

3>  由于匿名类型上的 Equals GetHashCode 方法是根据方法属性的 EqualsGetHashCode 定义的,因此仅当同一匿名类型的两个实例的所有属性都相等时,这两个实例才相等。

var

var是C#推出的弱化类型定义,也叫隐式类型。即可以不明确指定类型,由编译器去推断。

使用var的情况一般有以下几种

1>    不知道具体类型

如上面的声明匿名类和linq投影结果的情况。

2>    知道具体类型

在知道具体类型时使用var通常是为了少敲代码,比如

var dic = new Dictionary<string, string>();

         如果不使用var则需要如下定义

Dictionary<string, string> dic = new Dictionary<string, string>();

当然实际变成过程中还会遇到更长的类型。这种纯粹是为了少敲代码。

因为匿名类可以使用先定义的类代替,ling投影部分也可以使用具体类代替,所以代码中完全可以不使用var

比如

public class Stuff

        {

            public string Name { get; set; }

 

            public int Age { get; set; }

 

            public int ID { get; set; }

 

            public double Salary { get; set; }

        }

 

        public class SingleStuff

        {

            public string Name { get; set; }

 

            public int Age { get; set; }

 

            public SingleStuff(string name, int age)

            {

                this.Name = name;

                this.Age = age;

            }

        }

private void test()

        {

            Stuff[] arrStuffs = new Stuff[30];

            for (int i = 0; i < 30;i++)

            {

                arrStuffs[i] = new Stuff();

                arrStuffs[i].Name = "name" + i;

                arrStuffs[i].Age = 22 + i;

            }

            IEnumerable<SingleStuff> olders = from stuff in arrStuffs

                         where stuff.Age >= 30

                         select new SingleStuff(stuff.Name,stuff.Age);

            foreach (SingleStuff s in olders)

            {

                Console.WriteLine(s.Name + " : " + s.Age);

            }

        }

var在提供便利同时,也或多或少的降低了代码的可阅读行,所以个人认为除非是匿名类的情况,否则尽量避免使用var

使用var要注意以下几点

1>    声明var类型变量时必须初始化,并且不能初始化为null,否则编译器无法推断出你需要定义什么样的类型,而且一旦声明后就不能再更改其类型

2>    只能用作声明局部变量

3>    var是仔编译器推断的,所以实际运行时它就相当于直接使用推断出的类型,所以会有var效率上和使用强类型方式定义变量完全一样的说法。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值