匿名类型与元组(ValueTuple)

匿名类型与元组(ValueTuple)

匿名类型

简介:匿名类型提供了一种方便的方法,可用来将一组相关的属性封装到单个对象中。匿名对象由编译器在编译时动态生成,它是只读的,且只在当前作用域中可见。它可以方便地在代码中传递和
我的:不用写class直接new对象,组合数据,传递数据
好处:避免编写不必要的类,提高编码效率,逻辑更清晰
缺点:超出当前作用域,需使用dynamic或反射等方式来获取数据项
应用:匿名对象通常用在LINQ的select字句及多返回值场景
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace demo匿名类型
{
    public class Student
    {
        public int Id { get; set; }//学生编号
        public string Name { get; set; }//学生姓名
        public int Age { get; set; }//学生年龄
        public string Gender { get; set; }//学生性别
        public int ClassId { get; set; }//所在班级编号
    }
    public class Class
    {
        public int Id { get; set; }//班级编号
        public string ClassName { get; set; }//班级名称
        public string Teacher { get; set; }//班级教师
    }
}

using System.Reflection;
namespace demo匿名类型
{
    internal class Program
    {

        static void Main(string[] args)
        {
            /********创建使用匿名类型对象********/
            var person = new { Name = "张三", Sex = "男", Age = 11 };
            Console.WriteLine($"Name:{person.Name},Sex:{person.Sex},Age:{person.Age}");


            /*动态类型处理匿名对象类型。缺点:属性名写错了,也不会报错,运行时出错。*/
            dynamic GetStudentInfo()
            {
                return new { Name = "李四", Sex = "男", Age = 18 };
            }
            dynamic student = GetStudentInfo();
            Console.WriteLine($"Name:{student.Name},Sex:{student.Sex},Age:{student.Age}");


            /*****指定类型接受匿名对象类型(此技巧只在同一程序集中的代码才有效)*****/
            dynamic GetStudentInfo1()
            {
                return new { Name = "", Sex = "", Age = 0 };
            }
            dynamic student1 = GetStudentInfo1();
            Console.WriteLine($"Name:{student.Name},Sex:{student.Sex},Age:{student.Age}");


            /*****通过反射获取匿名类型数据项(测试匿名类型作参数)*****/
            void Test(object obj)
            {
                Type t = obj.GetType();
                PropertyInfo? pName = t.GetProperty("Name");
                PropertyInfo? pSex = t.GetProperty("Sex");
                PropertyInfo? pAge = t.GetProperty("Age");
                Console.WriteLine($"匿名类型:{t.Name}");
                Console.WriteLine($"Name:{pName?.GetValue(obj)},Sex:{pSex?.GetValue(obj)},Age:{pAge?.GetValue(obj)}");
            }
            Test(new { Name = "王五", Sex = "男", Age = 20 });

            /******linq支持对匿名对象集合的查询处理******/
            var people = new[]
            {
                new {Name = "李麻子" ,Sex = "男" , Age = 21 },
                new {Name = "八戒" ,Sex = "男" , Age = 40 },
                new {Name = "悟空" ,Sex = "男" , Age = 500 },
                new {Name = "唐僧" ,Sex = "男" , Age = 25 }
            };

            //班级信息列表
            var classList = new List<Class>
            {
                new Class{Id = 1 ,ClassName = "一年级一班" , Teacher = "张老师" },
                new Class{Id = 2 ,ClassName = "一年级二班" , Teacher = "王老师" },
                new Class{Id = 3 ,ClassName = "二年级一班" , Teacher = "赵老师" },
                new Class{Id = 4 ,ClassName = "二年级二班" , Teacher = "李老师" }
            };

            //学生信息列表
            var studentList = new List<Student>
            {
                new Student{Id = 1 ,Name = "张三" , Age = 8 ,Gender = "男",ClassId = 1},
                new Student{Id = 2 ,Name = "李四" , Age = 9 ,Gender = "女",ClassId = 2},
                new Student{Id = 3 ,Name = "王五" , Age = 8 ,Gender = "男",ClassId = 1},
                new Student{Id = 4 ,Name = "赵六" , Age = 9 ,Gender = "女",ClassId = 2},
                new Student{Id = 5 ,Name = "钱七" , Age = 7 ,Gender = "男",ClassId = 3},
                new Student{Id = 6 ,Name = "孙八" , Age = 7 ,Gender = "女",ClassId = 3}
            };

            var query = from p in people
                        where p.Age > 30
                        select p;

            foreach (var Person in query)
            {
                Console.WriteLine($"Name:{Person.Name},Sex:{Person.Sex},Age:{Person.Age}");
            }

            //使用LINQ进行联合查询,查询学生信息以及对应的班级信息
            var result = from s in studentList
                         join c in classList
                         on s.Id equals c.Id
                         select new
                         {
                            学生姓名 = s.Name,
                            年龄 = s.Age,
                            性别 = s.Gender,
                            班级名称 = c.ClassName,
                            班级教师 = c.Teacher
                         };

            //输出查询结果
            foreach (var item in result)
            {
                Console.WriteLine($"学生姓名:{item.学生姓名},年龄:{item.年龄}," +
                    $"性别:{item.性别},班级名称:{item.班级名称},班级教师:{item.班级教师}");
            }

            //使用 LINQ 进行联合查询,查询学生信息
            var result2 = from s in studentList
                         select new
                         {
                             s.Id, //注:此处可简写,没写属性名,自动以赋值属性为名称
                             s.Name
                         };

            //输出查询结果
            foreach (var item in result2)
            {
                Console.WriteLine($"学生ID:{item.Id},学生姓名:{item.Name}");
            }
        }
    }
}

元组ValueTuple使用技巧(一行代码交换两个变量的值)

            //数据互换(使用元组)
            string str1 = "长江";
            string str2 = "黄河";
            Console.WriteLine($"str1 = {str1}, str2 = {str2}");
            (str1,str2) = (str2,str1);
            Console.WriteLine($"str1 = {str1}, str2 = {str2}");

匿名类型与元组ValueTuple对比

  • 元组是一种泛型结构体,系统预定义好的;
  • 匿名类型不写class、new对象,元组也是一样;
  • 匿名类型 new{…},格式简介,元组更简洁(元素类型1,元素类型2,…)变量名;
            //使用元组(ValueTuple),将多个数据元素构成一个轻型数据结构
            (string, int) x = new ValueTuple<string, int>("鲁班七号",12);
            (string, int) y = ValueTuple.Create("鲁班七号",12);
            //更简洁的语法
            (string, int) z = ("鲁班七号",12);
            Console.WriteLine($"姓名:{z.Item1},年龄:{z.Item2}");
  • 匿名类型 属性名 = 属性值,元组ValueTuple 字段名:字段值
            //使用命名字段1
            var a = (name : "百里守约", age : 22);
            Console.WriteLine($"姓名:{a.name},\t年龄:{a.age}");
            //使用命名字段2
            (string name, int age) b = ("妲己",28);
            Console.WriteLine($"姓名:{b.name},\t年龄:{b.age}");

            //元组的解构
            (string name, int age) = ("廉颇",40);
            var (name1, age1) = ("廉颇",40);
            Console.WriteLine($"姓名:{name},\t年龄:{age}");
            Console.WriteLine($"姓名:{name1},\t年龄:{age1}");
  • 元组ValueTuple参数,返回值方便
            //弃元,放弃不需要的元素
            var tuple = (1,'a' ,3.14);
            var (_,letter,_) = tuple;
            Console.WriteLine(letter);

            //元组作为参数
            void ProcessTuple((string name,int Age)person)
            {
                Console.WriteLine($"Name:{person.name},Age:{person.Age}");
            }
            ProcessTuple(("东皇太一",80));

            //元组作为返回类型
            (int Sum, int Product)GetSumAndProduct(int a,int b)
            {
                return (a + b , a * b);
            }
            var result3 = GetSumAndProduct(3,4);
            Console.WriteLine($"和:{result3.Sum},乘积:{result3.Product}");

            //使用元组作为返回值
            (string, int) GetPerson()
            {
                return ("烬天玉藻前",30);
            }
            //调用方法并解构返回值
            (string name2, int age2) = GetPerson();
            Console.WriteLine($"Name:{name2},乘积:{age2}");
  • 匿名函数在LINQ中使用方便,元组ValueTuple也在LINQ中使用方便
            //使用LINQ进行联合查询,查询学生信息以及对应的班级信息
            var result5 = from s in studentList
                         join c in classList
                         on s.Id equals c.Id
                         select
                         (
                             学生姓名 : s.Name,
                             年龄 : s.Age,
                             性别 : s.Gender,
                             班级名称 : c.ClassName,
                             班级教师 : c.Teacher
                         );

            foreach (var item in result5)
            {
                Console.WriteLine($"学生姓名:{item.学生姓名},年龄:{item.年龄}," +
                    $"性别:{item.性别},班级名称:{item.班级名称},班级教师:{item.班级教师}");
            }
  • 元组字段值可修改
            //元组可以修改
            var f = (name : "关羽", age : 38);
            f.name = "东皇太一";
            Console.WriteLine($"姓名:{f.name},\t年龄:{f.age}");
  • 元组类型支持相等运算符 == 和 != ,它比较的是各个元素
            //元组类型支持相等运算符 == 和 != ,它比较的是各个元素
            var data = (2,2.3);
            if ((2, 2.31) == data)
            {
                Console.WriteLine("数据相等");
            }
            else
            {
                Console.WriteLine("数据不相等");
            }

            //元组中可以使用任意数量的元素。
            var t = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,"比尔盖茨");
            //系统已经帮我们重写了ToString方法,方便输出所有元素
            Console.WriteLine(t.ToString());

思维导图

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值