在本篇中我要介绍两个概念
我觉得这两个东西必须一起来介绍
这样才能连贯
C# 里我们已经匿名方法了现在类型也玩起匿名来了怪不得大家举报的时候都喜欢匿名为啥?因为匿名被举报人就找不着报复对象了呗是的匿名就是把名字隐藏起来没有名字谁还能找得到你啊
匿名类型
在C#里有这样一些类型它是作为临时储存数据的生命周期只在这个方法内方法结束了这个类型的生命周期也没有了那么这里我们就可以使用一个匿名类型
varKeyPair=new{Key=yuyiValue=};
这个KeyPair就是一个匿名类型注意KeyPair这里是一个变量名并不是类的名字嗯前面还有一个var这又是什么呢?这是C# 里面的隐式局部变量
隐式类型局部变量
还是先介绍一下隐式类型局部变量吧
在C# 里多了一个关键字var他表示这样的一种类型C#编译器可以根据上下文推断的出来比如var I = ;编译器可以根据后面的赋值推断的出来i应该是个整型既然是局部变量那么它就只能用在方法内部了注意C#是强类型的引入了一个var并不是像javascript那样变成了一个弱类型的语言在编译器第一次编译后var就会被确定的类型所替代的所以对于隐式类型局部变量要注意以下几点
它只能存在于方法内部
它不是一个新的类型只是一个关键字或者叫做一个占位符在C#编译器编译后它就会被确定的类型所替代
它是编译器根据上下文推断出来的所以所有一切不能被编译器推断出来的用法都是错误的比如不能这样使用var nullValue = null;因为null啥也不是他是一个空指针是一个不确定的东西也不能这样使用var I = ;I = abc;编译器根据第一个赋值会推断出它是一个整型但是随后又将一个字符串赋值给它这是怎么回事呢?
对于var我的建议是不到逼不得已的时候不用那什么是逼不得已呢?来看我们的匿名类型吧
回到匿名类型
刚才说了匿名类型是没有名字的类型没有名字你怎么来称呼它怎么来声明它?但是匿名类型真的是没有名字的么?
看看C#编译器又在我们背后干了些什么
使用ILDASM打开编译过的程序集发现多了一个类型
<>f__AnonymousType<<Key>j__TPar<Value>j__TPar>
这个类型是直接继承自SystemObject的并且是internal seald(只在程序集内可见并且不能被继承)有心的你也许会发现这个类型还是一个泛型类型那么只要我们在使用一个匿名类型的时候参数个数参数名称不发生变化编译器是不会为我们产生更多的类型的
varKeyPair=new{Key=yuyiValue=Programer};
varKeyPair=new{Key=yValue=};
varKeyPair=new{Key=Value=abc};
上面三个匿名类型编译器只会为我们在背后产生一个新类型一个泛型的新类型如果我们将这个匿名类型内的属性名修改一下对
varKeyPair=new{Key=yuyiValue=Programer};
varKeyPair=new{Key=yValue=};
就会产生两个新泛型了
<>f__AnonymousType<<Key>j__TPar<Value>j__TPar>
<>f__AnonymousType<<Key>j__TPar<Value>j__TPar>
看看这个命名还是有规律可循哦如果你给这个匿名类型添加一个新属性呢?这样又产生了一个新类型了
<>f__AnonymousType<<Key>j__TPar<Value>j__TPar<Test>j__TPar>
嗯这个问题还是值得关注的所以我们在使用匿名类型的时候应该尽量保持一致性
属性个数一致(这个尽量了)
属性名称一致这个比较好把握
只要保持了这个一致性编译器会为一致的产生同一个类型而不一致的会新产生一个类型如果不一致的太多我想是不是会产生代码爆炸而致使WorkSet过大造成性能的损失?这个只是我个人认为没有经过测试
继续隐式类型局部变量
由于匿名类型在我们编写代码的时候并不存在所以匿名类型也不能作为方法的返回值和参数了var一样也是只能在方法内部使用现在是不是有点明白什么时候才是逼不得已使用var啊?就是在使用匿名类型的时候匿名类型编译器可以推断出来但是靠人工又无法推断了所以我觉得只在编译器可推断而人不可推断的时候才使用隐式类型局部变量靠我们人工可以推断的还是不建议使用显式的声明变量类型可以增强代码的可读性这是一个好的编程习惯不要因为C# 提供了这样的特性就大用而特用