什么是C#匿名类型?
顾名思义,C#中的匿名类型是没有名称的类型,或者您可以在不定义它们的情况下创建新类型。C#匿名类型是在C#3.0中被引入的。
它是一个临时数据类型,基于对象初始化器中的数据来推断。或者换句话说,匿名类型提供了一种有效的方法,可以将一组只读对象组合到一个对象中,而不需要显式定义这个数据类型。
匿名类型的类型由编译器根据分配给其属性的值自动生成。
C#匿名类型使用关键字var
声明,并使用new
关键字初始化一个匿名类型。
C#匿名类型的语法格式如:
var anonymousName = new { [PropertyName] = [Value] };
其中的
anonymousName
为匿名类型的变量名,[PropertyName]为匿名类型anonymousName
的属性名,[Value]则为对应的属性值。属性名需要符合C#的属性命名规则,当为属性赋值后,编译器能推断这个属性的数据类型。
比如,我们要定义一个匿名的用户customer
,如下:
var customer = new { Id = 1, Name = "Rector" };
特别注意: 请和JavaScript中定义对象的格式作比较。JavaScript定义对象的格式形如:
var customer = { Id:1, Name:"Rector"}
这样,我们就声明了一个名为customer
的匿名类型,它包含了Id
和Name
两个属性。当然,你可以定义任意的属性名,只要符合C#的命名规范。
C#匿名类型的特征
C#匿名类型具有如下的特征:
- 任何的C#匿名类型均直接派生自
System.Object
基类,同时C#匿名类型还是一个密封类。因此,C#匿名类型的属性是只读的,也就意味着当匿名类型被初始化后就不能修改属性的值了 - Visual Studio中支持对C#匿名类型属性的智能感知
- 一个C#匿名类型可以包含一个或者多个属性
- C#匿名类型不能包含类型的成员,如:事件,方法等等
- 用于初始化属性值的表达式不能是
null
,或者匿名方法,或者一个指针类型 - 除了可以创建C#匿名类型对象外,你还可以创建匿名类型数组
- 不能被转换成除对象外的其他数据类型
- C#匿名类型是引用类型
- 不允许将方法、属性、构造函数、索引器的形式参数声明为匿名类型
- C#匿名类型的作用域总是局限于在定义它们的方法内,你不能从一个方法直接调用另外一个方法中的匿名对象
- C#匿名类型是泛型的,具有和属性一样多的类型参数
- C#匿名类型的每个属性都是公共的
- C#匿名类型的每个属性都有一个对应的私有字段
Visual Studio支持C#匿名类型的智能感知
通过上图我们可以看到,Visual Studio支持对C#匿名类型属性的动态智能感知功能,当我们使用变量customer
点的时候,Visual Stutio会自动提示customer
匿名类型对象所声明的属性,如示例中的Id
和Name
。这对提高开发效率是很有帮助的。同时,如果你输入一个未声明的属性,Visual Studio也会同样给出错误提示,如下图:
在方法内部使用匿名类型对象
以下示例为在某个方法内部定义并使用匿名类型对象:
public static void Run()
{
var customer = new { Id = 1, Name = "Rector"};
Console.WriteLine("Id:{0},Name:{1}", customer.Id, customer.Name);
}
输出结果为:
Id:1,Name:Rector
C#匿名类型嵌套
在C#匿名类型中,我们还可以嵌套数据类型,嵌套的数据类型可以是匿名类型,也可以是已定义的数据类型。
嵌套示例一(嵌套匿名类型对象):
var customer = new { Id = 1, Name = "Rector", Address = new { Country ="China" } };
Console.WriteLine("Id:{0},Name:{1},Country:{2}", customer.Id, customer.Name,customer.Address.Country);
嵌套示例二(嵌套特定类型对象,这里我们定义了一个Address
类):
var customer = new { Id = 1, Name = "Rector", Address = new Address { Country ="China" } };
Console.WriteLine("Id:{0},Name:{1},Country:{2}", customer.Id, customer.Name,customer.Address.Country);
Address.cs:
public class Address
{
public string Country { get; set; }
}
嵌套示例三(嵌套特定类型对象,这里我们定义了一个Address
类,在匿名对象声明之前先定义了Address
对象):
var Address = new Address { Country = "China" };
var customer = new { Id = 1, Name = "Rector", Address};
Console.WriteLine("Id:{0},Name:{1},Country:{2}", customer.Id, customer.Name,customer.Address.Country);
以上三个示例的运行结果是一样的。
C#匿名类型数组
以面介绍过,C#除了可以定义匿名类型外,还可以定义匿名类型数组,如下:
var customers = new[] {
new { Id = 1, Name = "Rector" },
new { Id = 2, Name = "Lee" }
};
foreach (var customer in customers)
{
Console.WriteLine("Id:{0},Name:{1},Country:{2}", customer.Id, customer.Name);
}
特别注意:匿名数组中的每一个匿名对象的属性名以及属性值类型要完全一致,否则编译器会报错,如:
匿名数组错误示例一(数组中匿名对象拥有的属性个数不一致):
var customers = new[] {
new { Id = 1, Name = "Rector" },
new { Id = 2, Name = "Lee",Age = 18 }
};
匿名数组错误示例一(数组中匿名对象属性值的数据类型不一致):
var customers = new[] {
new { Id = 1, Name = "Rector" },
new { Id = "2", Name = "Lee" }
};
从特定对象中抽取部分属性构造成匿名对象
本示例定义了一个Customer
类并初始化了一个customer
对象,随后使用这个customer
对象的部分属性构造了一个匿名的对象anonymousCustomer
,示例代码如下:
public class Customer
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime CreatedAt { get; set; }
}
public class AnonymousClassDemo
{
public static void Run()
{
var customer = new Customer
{
Id = 1,
FirstName = "Rector",
LastName = "Liu",
CreatedAt = DateTime.Now
};
var anonymousCustomer = new
{
customer.Id,
customer.FirstName,
customer.LastName,
FullName = string.Format("{0} {1}", customer.FirstName, customer.LastName)
};
Console.WriteLine("Id:{0},FullName:{1}", anonymousCustomer.Id, anonymousCustomer.FullName);
}
}
使用LINQ构造匿名对象集合
本示例演示的是如何使用LINQ从一个特定的对象集合中抽取一个匿名对象集合,如下:
public class Player
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public double PPG { get; set; }
}
public class AnonymousClassDemo
{
public static void Run()
{
// NBA的球员场得分数据(PPG:表示场均得分)--非真实数据
var players = new List<Player> {
new Player { Id = 1, FirstName = "Kevin", LastName = "Durant", PPG = 29.5 },
new Player { Id = 2, FirstName = "Stephen", LastName = "Curry", PPG = 26.7 },
new Player { Id = 3, FirstName = "James", LastName = "Harden", PPG = 25.8 },
new Player { Id = 4, FirstName = "Tracy", LastName = "McGrady", PPG = 30.6 },
};
// 提取场均得分超过26分的球员
var scorers = players.Where(x => x.PPG > 26).Select(x => new
{
x.Id,
Points = x.PPG,
FullName = string.Format("{0} {1}", x.FirstName, x.LastName)
});
foreach (var player in scorers)
{
Console.WriteLine("Id:{0}, Points:{1}, FullName:{2}",player.Id,player.Points,player.FullName);
}
}
}
运行结果为:
Id:1, Points:29.5, FullName:Kevin Durant
Id:2, Points:26.7, FullName:Stephen Curry
Id:4, Points:30.6, FullName:Tracy McGrady
版权声明:本作品系原创,版权归码友网所有,如未经许可,禁止任何形式转载,违者必究。
发表评论
登录用户才能发表评论, 请 登 录 或者 注册