动态类型dynamic是微软在.net framework 4.0开始引入的,其目的是在程序编译过程中忽略对类型的检查,等到运行时刻再明确定义的对象的类型。
使用dynamic类型可以简化代码。如下面代码所示,有学生类型Student,包括多种属性定义。
public class Student
{
public string Name;//姓名
public int Age;//年龄
public string Sex;//性别
public string Address;//住址
public string Grade;//年级
public string PhoneNumber;//电话号码
}
现在需要做的是根据用户的输入条件在一组学生数据中进行数据过滤。如果用户输入的条件为空,则返回所有数据,如果不为空,则返回满足条件的学生信息。不用返回每个学生的所有信息,只要有姓名、性别和住址即可。
最初的解决方式如下所示,根据条件是否为空,分别对学生信息集合进行处理,并返回及显示匿名对象集合。但是这段代码的问题是if和else中存在有重复代码,即显示检索结果那段是重复的。
string gradeFilter = Console.ReadLine();
if (string.IsNullOrEmpty(gradeFilter))
{
var result = from g in m_students
select new { Name = g.Name, Sex = g.Sex, Address = g.Address };
foreach (var item in result)
{
Console.WriteLine(string.Format("{0}-{1}-{2}", item.Name, item.Sex, item.Address));
}
}
else
{
var result = from g in m_students
where g.Grade==gradeFilter
select new { Name = g.Name, Sex = g.Sex, Address = g.Address };
foreach (var item in result)
{
Console.WriteLine(string.Format("{0}-{1}-{2}", item.Name, item.Sex, item.Address));
}
}
Console.ReadKey();
由于没有办法将var result的定义提前到if语句之前(VS:隐式类型化的变量必须已初始化),也没法将null值赋予result(VS:无法将<null>赋予隐式类型化的变量)。首先想到的解决办法是再定义一个学生信息类,只包括姓名、性别和住址三个属性,然后替换linq语句中的匿名对象。
这样虽然能够解决问题,但是却增加了代码量。这是就可以使用dynamic动态类型。
关于dynamic动态类型的详细介绍可以查看参考文献1-4。简而言之,使用dynamic动态类型定义的对象:“变量的使用和对其成员的引用绕过编译时类型检查。 改为在运行时解析这些操作”。也就是说VS在编译时不会去检查dynamic动态类型定义的对象以及对对象属性的操作,而是在程序运行时再去明确对象的具体类型。
于是将上述示例代码修改为以下方式,将result定义为dynamic动态类型,同时将显示过滤结果的代码放到最后,删除重复代码。程序的运行效果与上面的示例代码效果相同。
dynamic result;
string gradeFilter = Console.ReadLine();
if (string.IsNullOrEmpty(gradeFilter))
{
result = from g in m_students
select new { Name = g.Name, Sex = g.Sex, Address = g.Address };
}
else
{
result = from g in m_students
where g.Grade==gradeFilter
select new { Name = g.Name, Sex = g.Sex, Address = g.Address };
}
foreach (var item in result)
{
Console.WriteLine(string.Format("{0}-{1}-{2}", item.Name, item.Sex, item.Address));
}
Console.ReadKey();
上述内容是初步学习参考文献中关于dynamic动态类型的一些认识,理解的可能不全或有所偏颇,欢迎批评指正。
参考文献
[1]https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/builtin-types/reference-types#the-dynamic-type
[2]https://docs.microsoft.com/zh-cn/dotnet/api/system.dynamic.dynamicobject?view=net-5.0
[3]https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/types/walkthrough-creating-and-using-dynamic-objects
[4]https://www.dazhuanlan.com/2019/09/13/69ab7f586028/