var和dynamic的应用 var、动态类型 dynamic 深入浅析C#中的var和dynamic ----demo

时间:2022-10-13 07:34:40
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" };
        }
    }
}