首页 / C#开发 / 正文

C#匿名类型详解--什么是C#匿名类型?C#匿名类型有哪些特征?

8151 发布于: 2019-06-12 读完约需15分钟

什么是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的匿名类型,它包含了IdName两个属性。当然,你可以定义任意的属性名,只要符合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#匿名类型的智能感知

通过上图我们可以看到,Visual Studio支持对C#匿名类型属性的动态智能感知功能,当我们使用变量customer点的时候,Visual Stutio会自动提示customer匿名类型对象所声明的属性,如示例中的IdName。这对提高开发效率是很有帮助的。同时,如果你输入一个未声明的属性,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

版权声明:本作品系原创,版权归码友网所有,如未经许可,禁止任何形式转载,违者必究。

上一篇: C#/.NET WPF应用程序编程开发中如何获取当前程序所有目录的路径?

下一篇: C#/.NET应用程序编程开发中如何判断一个对象是否为匿名对象?

本文永久链接码友网 » C#匿名类型详解--什么是C#匿名类型?C#匿名类型有哪些特征?

分享扩散:

发表评论

登录用户才能发表评论, 请 登 录 或者 注册