using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Newtonsoft.Json; using System.ComponentModel; namespace var_dynamic { class Program { //var stradsa = "asdasdas"; //报错 static void Main(string[] args) { #region var 接收一种类型后 在接受其他类型会报错 编译时解析 编译器会在编译过程中帮我们创建一个具有相关属性和方法的类型。 类型由赋于的值来决定 //还有一点 var 仅能声明方法内的局部变量(只能存在方法体里面 外面就报错) "; Console.WriteLine(a123); //a123 = 456; //报错 错误 1 无法将类型“int”隐式转换为“string” //var 声明的变量在被赋值后类型即确定下了,后续程序中不能在赋其他类型的值 var xwyy = new object();//没有意义 不要写这样的代码 #endregion #region 匿名类型集合 通过反射读取object 对应的属性名 //var xss = new { name = "a", Id = 1 }; //var list = (new int[] { 1 }).Select(x => new { Name = "张三", Num = 123 }).ToList(); var listss = new List<object>(); listss.Add(" }); listss.Add(" }); bool ishave = false; foreach (var item in listss) { PropertyDescriptorCollection pdc = TypeDescriptor.GetProperties(item); PropertyDescriptor pdID = pdc.Find("Address", true); var x = pdID.GetValue(item); Console.WriteLine("xxxx " + x); PropertyDescriptor pdName = pdc.Find("Tel", true); var z = pdName.GetValue(item); Console.WriteLine("zzzz " + z); //if (x.ToString() == x && z.ToString() == z) //{ // ishave = true; // break; //} } #endregion #region dynamic 接收一种类型后 接受其他类型不会报错 运行时解析 //随用随定义,用完就消失 "; Console.WriteLine(b123); b123 = ; Console.WriteLine(b123); b123 = " }; Console.WriteLine(b123.Id); #endregion #region object 接收任意类型 但取值 要转换为 对应类型 object对象无法 解析 定义成员 "; c123 = ; c123 = " }; //Console.WriteLine(c123.name); //报错 错误 1 “object”不包含“name”的定义,并且找不到可接受类型为“object”的第一个参数的扩展方法“name”(是否缺少 using 指令或程序集引用?) //从object 取出 Id name 就要用 dynamic dynamic dyc123 = c123; Console.WriteLine(dyc123.name); #endregion #region var 可以解析 详情 可看 .NET中那些所谓的新语法之二:匿名类、匿名方法与扩展方法 // 反编译为 泛型类 类似 <>f__AnonymousType0<<ID>j__TPar, <Name>j__TPar, <Age>j__TPar> // 属性只读 重写了3个基类方法 Equals GetHashCode Tostring //匿名类共享 符合一定条件则可以共享一个泛型类 //属性类型和顺序都一致,那么默认共享前一个泛型类 //属性名称和顺序一致,但属性类型不同,那么还是共同使用一个泛型类,只是泛型参数改变了而已,所以在运行时会生成不同的对象: //数据型名称和类型相同,但顺序不同,那么编译器会重新创建一个匿名类 var annoyCla1 = new { ID = , Name = "EdisonChou", Age = }; Console.WriteLine(annoyCla1.Name); #endregion #region dynamic 可读可写 dynamic expando = new System.Dynamic.ExpandoObject(); //动态类型字段 可读可写 expando.Id = ; expando.Name = "Test"; string json = JsonConvert.SerializeObject(expando); //输出{Id:1,Name:'Test'} #endregion #region 动态添加字段 Console.WriteLine("动态添加字段"); List<string> fieldList = new List<string>() { "Name", "Age", "Sex" }; //From config or db dynamic dobj = new System.Dynamic.ExpandoObject(); var dic = (IDictionary<string, object>)dobj; foreach (var fieldItem in fieldList) { dic[fieldItem] = "set " + fieldItem + " value"; /*实现类似js里的 动态添加属性的功能 var obj={}; var field="Id"; eval("obj."+field+"=1"); alert(obj.Id); //1 */ } var val = dobj.Name; //“set Name value” var val1 = dobj.Age;//”set Age value“ #endregion #region 枚举该对象所有成员 Console.WriteLine("枚举该对象所有成员"); foreach (var fieldItem in (IDictionary<String, Object>)dobj) { var v = (fieldItem.Key + ": " + fieldItem.Value); Console.WriteLine(v); } #endregion #region 匿名类 Console.WriteLine("匿名类"); //var aaaa = new {Id=1,Name="Test"}; //匿名类字段只读不可写 // 切记 就算 用运行解析装起来 也不行 还是表示 匿名类型 , Name = "Test" }; //匿名类字段只读不可写 //aaaa.Id = 2; //不可写 报错无法为属性或索引器“<>f__AnonymousType1<int>.Id”赋值 - 它是只读的 dynamic obj = Newtonsoft.Json.JsonConvert.DeserializeObject("{Name:'aa',Sex:'Male',Age:11}"); var name = obj.Name.Value; //aa Console.WriteLine(name); #endregion #region 返回一个匿名对象 方法返回值 类型无法确定 方法返回的对象不确定怎么办 返回object ? 返回dynamic var xs1 = GetObject(); //xs1.Name; //object点不出来 要用反射 //此时方法不会出现语法错误,程序可以成功编译并执行 //dynamic 表示动态类型,动态类型的含义就是 程序编写、编译阶段 类型不确定,在Runtime时再通过反射机制确定相关对象的属性或方法。因此编写阶段 不会进行语法检测。 //dynamic 可用来声明 字段、属性、方法参数、方法返回值 //dynamic 不支持智能提示,因为你写代码时 dynamic 是什么没法知晓(反射) //dynamic 声明的变量,可理解为 object 类型变量。所以给dynamic变量赋任何类型值都正确,但在使用变量来取得某个属性值或调用某方法时(此时程序肯定处于Runtime状态),CLR会检查(反射)所调用的属性或方法是否存在,不存在报运行时异常。 //dynamic在 Asp.net Mvc web开发中处处使用,虽然看上去很复杂,本质就上面所说内容。 // var dynamic // 声明字段 × √ // 局部变量 √ √ // 方法参数类型 × √ // 方法返回值类型 × √ Console.WriteLine(xs1.Name); // dynamic 就很方便 #endregion #region var关键字 静态类型语言也被称为强类型语言 就是在编译过程中执行类型检查的语言 //间接 定义数据类型的方式 string str001 = "Test";// 这种写法被称为显式类型的声明,也被称为直接声明。 var str = "Test";//这被称为隐式类型声明或间接类型声明。 //编译器会在编译过程中验证数据,并在编译过程中创建适当的类型。在此实例中,编译器将检查Test,并在生成IL代码时将var关键字替换为字符串类型。 //var关键字在编译时静态的定义数据类型,而不是在运行时,即:一旦定义了数据类型,它将不会在运行时更改。 var str002 = "Test"; //str002 = 123; //编译错误 隐式转换抛出编译错误 //对于像int、double、string等简单数据类型,我们最好使用特定的数据类型来声明变量,以免让事情变得复杂。但当你创建了一个很大的类,那么为了方便创建对象,你最好使用var关键字。还有一种约定俗成的习惯,当我们使用LINQ或Anonymous类型时,一般使用var关键字。 #endregion #region 动态类型语言 运行时执行类型检查的语言。如果您不知道您将获得或需要分配的值的类型,则在此情况下,类型是在运行时定义的 dynamic str0002 = "Test"; //在为 str0002 分配值之后,如果执行一些数学运算,它不会给出任何错误信息。 str0002++; // 编译通过 生成也成功 但是,如果你运行这个应用程序,对不起,VS会给你如下所示的运行时错误: //dynamic关键字内部使用反射,感兴趣的童鞋可以自行研究一下。 // var和dynamic关键字之间的主要区别在于绑定时间不一样:var是早期绑定,dynamic绑定则会在运行时进行。 //var实际上是编译器抛给我们的语法糖,一旦被编译,编译器就会自动匹配var变量的实际类型,并用实际类型来替换该变量的声明,等同于我们在编码时使用了实际类型声明。而dynamic被编译后是一个Object类型,编译器编译时不会对dynamic进行类型检查。 //.Net 4.0之前的运行时的动态调用一般是通过反射来实现,但是反射的代码的可读性不高。.Net 4.0之后使用dynamic就好得多,因为dynamic是一种静态类型,完全可以像其它类型一样的声明和调用,而不用写反射相关的代码。 //合理的运用dynamic可以让你的代码更加的简洁,而且比直接使用反射性能更好(反射没有优化处理的前提),因为dynamic是基于DLR,第一次运行后会缓存起来。其实有心的同学会发现.net的类库里面很多地方都用了dynamic这个东西,例如:mvc中的ViewBag就是一个很好的例子。一般情况下,如果开发者不知道方法和方法的返回类型是否公开,请使用dynamic关键字。 //补充:C# var和dynamic的用法和理解 //var和dynamic的本质区别是类型判断的时间不同,前者是编译时,后者是运行时。 //1.var在声明变量方面简化语法(只能是局部变量),在编译时交给编译器推断。 //2.dynamic也是为简化语法而生的,它的类型推断是交给系统来执行的(运行时推断类型)。 //3.var不能用于字段、参数等,而dynamic则可以。 //4.var在初始化的时候就确定了类型。 //5.dynamic可以用于方法字段、参数、返回值以及泛型参数,把动态发挥的淋漓尽致。 //6.dynamic在反射方面做的可以,只是我自己没有尝试过。 //7.var是C# 3.0的产物,dynamic是C# 4.0的产物。 //最后还得关心一下效率问题: // 越底层的效率越高 //可以说是 传统强类型 >= var > dynamic,所以用dynamic的时候还得考虑性能和效率! #endregion Func<; //var hui2 = () => 5; //错误 1 无法将“lambda 表达式”赋予隐式类型的局部变量 // var 不是一个匿名函数,同时初始化表达式也不能是 null; } //private static object GetObject() //private static var GetObject() 不支持 报错 private static dynamic GetObject() { , Like = "LOL" }; } } }