15.C#回顾及匿名类型(八章8.1-8.5)

  今天的篇幅应该会很长,除了回顾前面学的一些,还有写一些关于匿名类型的相关知识,总体上对后续的学习很有帮助,学好了,后面更容易理解,不明白的,那就前面多翻几次,看多了总是会理解的。那么,进入正题吧。

  • 自动实现属性

  我们的很多工作都是由编译器帮我们去完成,如我们要说的自动实现属性。使用自动实现属性时,C#3执行了一个简单的编译转换,在类的内部生成一个私有的字段,使用不友好的命名(防止命名冲突)。在C#2中允许为取值和赋值方法指定不同的访问权限,现在我们还可以创建静态的自动属性。

  • 隐式类型

  使用隐式类型,在编写代码时,没有显式地声明类型,但在编译的结果中,编译器会获取初始化表达式的类型,使用变量也具有该类型。隐式类型只有在以下几种情况才能使用:

  1. 被声明的变量是一个局部变量,而不是一个静态字段和实例字段
  2. 变量声明的同时需要初始化
  3. 初始化表达式不能是方法组,也不是匿名函数
  4. 初始化表达式不是null
  5. 语句中只声明了一个变量
  6. 初始化表达式不能包含正在使用的变量
  • 初始化

  一种方法是使用无参的构造函数先实例化一个对象,然后分别为每个公开的属性赋值。另一种则是在构造函数中将属性值作为参数,在构造函数中为每个属性赋值,这里可以给公开和私有的赋值。使用自动实现属性,则可以使用对象初始化器,如下,三个类Computer、Mouse、User

 1 class Computer
 2 {
 3     public string Cpu { get; set; }
 4     public Mouse Mouse { get; set; }
 5     public List<User> Users { get; set; }
 6 }
 7 class Mouse
 8 {
 9     public string Brand { get; set; }
10 }
11 class User
12 {
13     public string Name { get; set; }
14 }

  上述三个类都没有构造函数(有一个默认的无参构造函数),使用对象初始化器就能很方便的去实例化对象。

 1 Computer c = new Computer()
 2 {
 3     Cpu = "AMD",
 4     Mouse = new Mouse() { Brand = "罗技" },
 5     Users = new List<User> {
 6         new User() {Name="小A" },
 7         new User() {Name="小B" },
 8         new User() {Name="小C" }
 9     }
10 };

  可以看到上述的每一个对象实例都使用了对象初始器来实例化对象,调用的构造函数都是系统默认的构造函数,当我们将无参的构造函数设置为私有时,上述语句将无效。那我们就可以想像,当有一个为Cup赋值的构造函数,则在new Computer(cupName)接大括号"{}"来初始化对象,如

 1 class Computer
 2 {
 3     public string Cpu { get; set; }
 4     public Mouse Mouse { get; set; }
 5     public List<User> Users { get; set; }
 6     public Computer(string cpu) {
 7         this.Cpu = cpu;
 8     }
 9     public Computer()
10     {
11
12     }
13 }
14
15 Computer c1 = new Computer("AMD")
16 {
17     Mouse = new Mouse() { Brand = "罗技" },
18     Users = new List<User> {
19         new User() {Name="小A" },
20         new User() {Name="小B" },
21         new User() {Name="小C" }
22     }
23 };

  注:调用无参的构造函数时,使用省略类名后面的括号。

  是不是看上面的代码不断是很多,那我们可以再精简一下new List<User>,和new Mouse。

1  Computer c1 = new Computer("AMD")
2 {
3     Mouse = { Brand = "罗技" },
4     Users = {
5         new User() {Name="小A" },
6         new User() {Name="小B" },
7         new User() {Name="小C" }
8     }
9 };

  我们直接将类型名称给去除了,看到这里是否也想到可以把new User也给去除了,不过我试过是不行的,应该是无法确定要转换的类型吧。这个有点类似在C++11中统一使用"{}"来初始化对象。关于集合初始化可以参照上述中的对属性Users的初始化,而上述中Mouse = { Brand = "罗技" }则称呼为初始化嵌入对象。

  • 隐式类型的数组

  在C#1和C#2中,数组的声明和初始化如下

1 string[] names = { "a", "b", "c" };

  如果一个方法的签名如下:

1 public void Method0(string[] names)

  那使用大括号中的表达式不能作为参数传入该方法,如

1 Method0({ "a", "b", "c" });

  必须要告诉编译器传入的数组是什么类型的数组,如

1 Method0(new string[] { "a", "b", "c" });

  但如果我们显式的指定类型,可以让编译器自己推断,则用到了隐式类型数组,里面也有涉及到协变性,如果A继承于B,参数为A的数组,那么我们使用隐式类型的数组,就可以传入A实例和B实例的数组。如:

 1 class A
 2 {
 3 }
 4
 5 class B : A
 6 {
 7 }
 8
 9 public static void Method1(A[] args)
10 {
11
12 }
13
14 A a = new A();
15 B b = new B();
16 Method1(new[] { a, b });
17 Method1(new[] { new A(), new B() });
  • 匿名类型

  匿名类型常用作用于LINQ中返回一系列的没有具体类型名的对象,也可以使用单独使用(在不想创建多余的类时)。

1 var p = new { Name = "a", Age = 12 };

  接下来,就可以使用变量p,p有两个属性Name="a"和Age=12,也可以使用匿名类型来初始化数组,如

1 var ps = new[] {
2        new { Name = "a", Age = 12},
3        new { Name = "a", Age = 12},
4        new { Name = "a", Age = 12}
5 };

  匿名类型包含以下成员:

  1. 一个获取所有初始值的构造函数
  2. 公有的只读属性
  3. 属性的私有字段
  4. 重写了由object中继承的方法

  关于投影初始化程序,简单地理解从一个集合中,抽取集合元素中的各别属性,组成一个匿名类型,从而返回一个包含匿名类型的集合,这也是为什么我们使用var关键字,因为我们真的不知道返回的类型,使用var让编译器替我们理解返回类型,那问题来了,这个匿名类型的声明是否由编译器帮我们生成?它帮我们生成了类型,使用反编译工具就能知晓。

  请斧正。

时间: 2024-12-19 12:47:08

15.C#回顾及匿名类型(八章8.1-8.5)的相关文章

看看这个超级实用的一种类型——匿名类型

既然说到匿名类型超级实用,得要找到场景来说服一下,如果大家玩过php,里面有一个万能的关联数组array,任你在关联数组array里面怎么写,都 可以用json_encode来生成json,非常非常的方便. <?php //可以这么写 $arr= array("name"=>"hxc","age"=20,"isMale"=>true); //也可以这么写 $arrayName = array("li

隐式类型、对象集合初始化、匿名类型

隐式类型和对象集合初始化器是在C# 3.0中引入的. 1 隐式类型 var关键字,主要还是编译器根据变量的值来推断其类型. 1.1隐式类型的局部变量 1 class Program 2 { 3 static void Main(string[] args) 4 { 5 var stringvariable="learning hard"; 6 stringvariable=2; 7 } 8 } 其实当你把鼠标放在var上面的时候,还是可以看到其类型的. 使用隐式类型时有一些限制,包括一

Linq专题之提高编码效率—— 第二篇 神一样的匿名类型

说起匿名类型,我们都知道这玩意都是为linq而生,而且匿名类型给我们带来的便利性大家在实战中应该都体会到了,特别适合于一次性使用,临时 使用这些场景,虽然说是匿名类型,也就是说是有类型的,只是匿名了而已,对吧,这篇我们就来探索下匿名类型到底和linq有多大关系呢??? 一:select中的匿名类型 这个我想大家用的是最多的,毕竟你select之后需要把原始数据重塑成另一种形状展示出来,不信你看嘛!!! 1 class Program 2 { 3 static void Main(string[]

C++11 局部和匿名类型作模板实参

[1]C++11支持局部的类型和匿名类型做模板的实参 在C++98中,标准对模板实参的类型还有一些限制. 具体地讲,局部的类型和匿名的类型在C++98中都不能做模板类的实参. 而在C++11标准中,支持做模板的实参.示例如下: 1 template<typename T> class X {}; 2 template<typename T> void TempFun(T t) {}; 3 4 struct A { } a; 5 struct { int i; } b; // b是匿

定义类+类实例化+属性+构造函数+匿名类型var+堆与栈+GC回收机制+值类型与引用类型

为了让编程更加清晰,把程序中的功能进行模块化划分,每个模块提供特定的功能,而且每个模块都是孤立的,这种模块化编程提供了非常大的多样性,大大增加了重用代码的机会. 面向对象编程也叫做OOP编程 简单来说面向对象编程就是结构化编程,对程序中的变量结构划分,让编程更清晰. 类的概念: 类实际上是创建对象的模板,每个对象都包含数据,并提供了处理和访问数据的方法. 类定义了类的每个对象(称为实例)可以包含什么数据和功能. 类中的数据和函数称为类的成员:数据成员        函数成员 数据成员: 数据成员

编写高质量代码改善C#程序的157个建议——建议26:使用匿名类型存储LINQ查询结果

建议26:使用匿名类型存储LINQ查询结果 从.NET3.0开始,C#开始支持一个新特性:匿名类型.匿名类型有var.赋值运算符和一个非空初始值(或以new开头的初始化项)组成.匿名类型有如下基本特性: 即支持简单类型也指出复杂类型.简单类型必须是一个非空初始值,复杂类型则是一个以new开头的初始化项. 匿名类型的属性是只读的,没有属性设置器,它一旦被初始化就不可更改. 如果两个匿名类型的属性值相同,那么就认为这两个匿名类型相等. 匿名类型可以再循环中用作初始化器. 匿名类型支持智能感知. 匿名

C#超级实用的一种类型—匿名类型

顾名思义 匿名类型就是没有名字的类型.当一个新的匿名对象定义与前面已经存在的类型定义的内部变量类型相同时,编译器就会只生成一个类定义,而不是各一个.匿名类型对象中仍然可以再包含匿名对象. 在C#3.0中允许我们在程序中声明一个临时的类型来存储数据,例如: class Program { static void Main(string[] args) { //声明一个匿名对象,拥有 Name和Age 属性 var obj = new { Name = "Joey", Age = 25 }

如何把匿名类型.GetType()返回的对象传进泛型里面[转]

//怎么取得匿名类型的Type放到 //泛型T当中?? var 匿名 = new { A = 0, B = 1 }; Type t = 匿名.GetType(); //然后下面 var xx = dbContext.Database.SqlQuery<t>("sql"); //就悲剧了 var xx2 = dbContext.Database.SqlQuery<dynamic>("sql"); //xx2有列表,但是都是Object..~~~

C# 匿名类型

c#3.0引入匿名类型,其由编译器动态生成而非显式定义. using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks; namespace Project5_33{    class Program    {        static void Main(string[] args)        {            var p