标签:math generic amp false 部分 [] eof efault form
5 本章内容:
PS:以下代码以装箱和拆箱的说明居多
using System; using System.Collections; using System.Collections.Generic; using System.Reflection; using System.Dynamic; using System.Linq; using Microsoft.CSharp.RuntimeBinder; /////////////////////////////////////////////////////////////////////////////// public static class Program { public static void Main() { PrimitiveDemo(); BoxingDemo(); ReferenceVsValue.Go(); Boxing.Go(); BoxingForInterfaceMethod.Go(); MutateViaInterface.Go(); DynamicDemo.Go(); } private static void PrimitiveDemo()//P99-100 { //以下4行都能正确的编译,并生成相同的IL代码 int a = new int(); //不方便的语法 int b = 0; //最方便的语法 System.Int32 c = new System.Int32(); //最不方便的语法 Int32 d = 0; //方便的语法 Int32 int 是等价的 // 显示全部变量为0 Console.WriteLine("a = {0}, b = {1}, c = {2}, d = {3}", new Object[] { a, b, c, d }); // 设置全部的值为5 a = b = c = d = 5; Console.WriteLine("a = {0}, b = {1}, c = {2}, d = {3}", new Object[] { a, b, c, d }); } private static void BoxingDemo() { Int32 a = 5; // 创建未装箱的值类型变量 Object o = a; // o引用已装箱的a的版本 a = 123; // 修改未装箱的值 123 Console.WriteLine(a + ", " + (Int32)o); // 显示 "123, 5" Console.WriteLine(a + ", " + o); // 优化 Console.WriteLine(a); // 没有装箱 } //引用类型vs值类型 private static class ReferenceVsValue { //引用类型 (因为 ‘class‘) private class SomeRef { public Int32 x; } // 值类型 (因为 ‘struct‘) private struct SomeVal { public Int32 x; } public static void Go()//P(107) { SomeRef r1 = new SomeRef(); // 在堆上分配 SomeVal v1 = new SomeVal(); // 在栈是分类 r1.x = 5; // 提领指针 v1.x = 5; // 在栈上修改 Console.WriteLine(r1.x); // 显示 "5" Console.WriteLine(v1.x); // 同样显示 "5" //图5-2的左半部分反映了执行以上代码之后的情况 SomeRef r2 = r1; // 只复制应用(指针) SomeVal v2 = v1; // 在栈上分配并复制成员 r1.x = 8; // r1.x 和 r2.x 都会改变 v1.x = 9; // v1.x 会变, v2.x 不变 Console.WriteLine(r1.x); // 显示 "8" Console.WriteLine(r2.x); // 显示 "8" Console.WriteLine(v1.x); // 显示 "9" Console.WriteLine(v2.x); // 显示 "5" //图5-2的右半部分反映了执行以上所有代码之后的情况 } } private static class Boxing { public static void Go()//P(111) { ArrayList a = new ArrayList(); Point p; //分配一个Point(不在堆中分配). for (Int32 i = 0; i < 10; i++) { p.x = p.y = i; // 初始化值类型中的成员 a.Add(p); // 对值的类型装箱,将引用添加到ArrayLis中 } } // 声明一个值类型 private struct Point { public Int32 x, y; } public static void Main2()//P(113) { Int32 x = 5; Object o = x; // 对x装箱,o引用已装箱对象 Int16 y = (Int16)o; // 抛出 InvalidCastException 异常 } public static void Main3()//P(113) { /* Main2 方法正确的转化方式 */ Int32 x = 5; Object o = x; // 对x进行装箱,o引用已装箱对象 Int16 y = (Int16)(Int32)o; // 先拆箱为正确类型,再转型 } public static void Main4() { Point p; p.x = p.y = 1; Object o = p; //对P进行装箱 p = (Point)o; //对o进行拆箱,将字段从已装箱实例复制到栈变量中 } public static void Main5() { Point p; p.x = p.y = 1; Object o = p; // 对p进行装箱;o引用已装箱的实例 // 将 Point的字段变成2 p = (Point)o; // 对o拆箱,将字段从已装箱的实例复制到栈变量中 p.x = 2; // 更改栈变量的状态 o = p; // 对p装箱;o引用新的已装箱实例 } public static void Main6()//P(114) { Int32 v = 5; // 创建未装箱值类型变量 Object o = v; // o引用已装箱的,包含值5的Int32 v = 123; // 改变为装箱的的值改成123 Console.WriteLine(v + ", " + (Int32)o); // 显示 "123, 5" } public static void Main7()//P(116) { Int32 v = 5; // 创建未装箱值类型变量. Object o = v; // o 引用v的已装箱版本 v = 123; //将未装箱的值类型修改成123 Console.WriteLine(v); // 显示 "123" v = (Int32)o; //拆箱并将o复制到v Console.WriteLine(v); // 显示 "5" } public static void Main8()//P(117) { Int32 v = 5; // 创建未装箱的值类型变量 #if INEFFICIENT // 编译下面这一行,v 被装箱3次,浪费时间和内存 Console.WriteLine("{0}, {1}, {2}", v, v, v); #else // 下面的代码结果一样,但无论执行速度, // 还是内存利用,都比前面的代码更胜一筹 Object o = v; // 对v手动装箱(仅一次) // 编译下面这一行不发生装箱 Console.WriteLine("{0}, {1}, {2}", o, o, o); #endif } } private static class BoxingForInterfaceMethod { private struct Point : IComparable //p(118) { private Int32 m_x, m_y; //构造器负责初始化字段 public Point(Int32 x, Int32 y) { m_x = x; m_y = y; } //重写从System.ValueType 继承的ToString方法 public override String ToString() { //如果调用了 base.ToString() 则会被装箱 //将point做字符串返回。注意:调用ToString以避免装箱 return String.Format("({0}, {1})", m_x, m_y); } // 实现类型安全的CompareTo方法 public Int32 CompareTo(Point other) { // 利用勾股定理计算哪个point距离原点(0,0)更远 return Math.Sign(Math.Sqrt(m_x * m_x + m_y * m_y) - Math.Sqrt(other.m_x * other.m_x + other.m_y * other.m_y)); } // 实现IComparable 的 CompareTo 方法 public Int32 CompareTo(Object o) { if (GetType() != o.GetType()) { throw new ArgumentException("o is not a Point"); } // 调用类型安全的ComareTo方法 return CompareTo((Point)o); } } public static void Go() //P(119) { // 在栈上创建2个Point的实例 Point p1 = new Point(10, 10); Point p2 = new Point(20, 20); // 调用ToString(虚方法)不装箱p1; Console.WriteLine(p1.ToString()); // 显示"(10, 10)" // 调用GetType(非虚方法)时,要对P1进行装箱 Console.WriteLine(p1.GetType()); // 显示"Point" //调用CompareTo 不装箱p1 //由于调用的是CompareTo(Point),所以p2不装箱 Console.WriteLine(p1.CompareTo(p2)); // "-1" // p1要装箱,引用放到c中 IComparable c = p1; Console.WriteLine(c.GetType()); // 显示"Point" //调用CompareTo不装箱p1 //由于CompareTo传递不是Point变量 //所以调用的是CompareTo(Object),它要求获取对装箱Point的引用 //c不装箱是因为本来就引用了已装箱Point Console.WriteLine(p1.CompareTo(c)); // 显示"0" // c不装箱,因为它本来就引用了已装箱Point // p2要装箱,因为调用的是CompareTo(Object) Console.WriteLine(c.CompareTo(p2)); // "-1" //对c拆箱,字段复杂到P2中 p2 = (Point)c; // 证明字段已复制到P2中 Console.WriteLine(p2.ToString()); // "(10, 10)" } } private static class MutateViaInterface { // 接口定义了Change方法 private interface IChangeBoxedPoint { void Change(Int32 x, Int32 y); } // Point是值类型. private struct Point : IChangeBoxedPoint { private Int32 m_x, m_y; public Point(Int32 x, Int32 y) { m_x = x; m_y = y; } public void Change(Int32 x, Int32 y) { m_x = x; m_y = y; } public override String ToString() { return String.Format("({0}, {1})", m_x, m_y); } } public static void Go() { Point p = new Point(1, 1); Console.WriteLine(p); p.Change(2, 2); Console.WriteLine(p); Object o = p; Console.WriteLine(o); ((Point)o).Change(3, 3); Console.WriteLine(o); // 对p进行装箱,更改已装箱的对象,然后丢弃它 ((IChangeBoxedPoint)p).Change(4, 4); Console.WriteLine(p); // 更改已装箱的的对戏,并显示它 ((IChangeBoxedPoint)o).Change(5, 5); Console.WriteLine(o); /********************* 如果把Point 改成class 引用类型 就不存在装箱,拆箱的的转化,上面的结果就会发变化 ********************/ } } private static class DynamicDemo { public static void Go() { ShowLoadedAssemblies("Assemblies loaded before use of dynamic"); SimpleDynamic(); ShowLoadedAssemblies("Assemblies loaded after simkple use of dynamic"); Demo(); ShowLoadedAssemblies("Assemblies loaded after all dynamic code runs"); ExcelAutomation(); DynamicStaticInvocations(); } private static void ShowLoadedAssemblies(String caption) { Console.WriteLine(caption); foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies()) Console.WriteLine(" " + a.GetName().Name); Console.WriteLine(); } private static Int32 SimpleDynamic() { return ((dynamic)0) + 0; } private static void Demo() //P(129) { dynamic value; for (Int32 demo = 0; demo < 2; demo++) { value = (demo == 0) ? (dynamic)5 : (dynamic)"A"; value = value + value; M(value); } Object o = 123; // OK: 从Int32 隐形转型为Object(装箱) //Int32 n1 = o; // Error: 不允许从Object到Int32的隐式转化 Int32 n2 = (Int32)o; // OK: 从Object显示转型为Int32(拆箱) dynamic d = 123; // OK: 从 Int32 隐形转化为 dynamic(装箱) Int32 n3 = d; // OK: 从 dynamic 隐式转为 Int32(拆箱) try { var m = M(d); // 注意: ‘var m‘ 等同于 ‘dynamic m‘ } catch (RuntimeBinderException) { } var x = (Int32)d; // ‘var x‘ 等同于 ‘Int32 x‘ var dt = new DateTime(d); // ‘vat dt‘ 等同于 ‘DateTime dt‘ } private static void M(Int32 n) { Console.WriteLine("M(Int32): " + n); } private static void M(String s) { Console.WriteLine("M(String): " + s); } /// <summary> /// 构造一个 ‘dynamic‘ 的实例派生类,来动态调用类型的静态成员 /// </summary> internal sealed class StaticMemberDynamicWrapper : DynamicObject //P(132) { private readonly TypeInfo m_type; public StaticMemberDynamicWrapper(Type type) { m_type = type.GetTypeInfo(); } public override IEnumerable<String> GetDynamicMemberNames() { return m_type.DeclaredMembers.Select(mi => mi.Name); } public override bool TryGetMember(GetMemberBinder binder, out object result) { result = null; var field = FindField(binder.Name); if (field != null) { result = field.GetValue(null); return true; } var prop = FindProperty(binder.Name, true); if (prop != null) { result = prop.GetValue(null, null); return true; } return false; } public override bool TrySetMember(SetMemberBinder binder, object value) { var field = FindField(binder.Name); if (field != null) { field.SetValue(null, value); return true; } var prop = FindProperty(binder.Name, false); if (prop != null) { prop.SetValue(null, value, null); return true; } return false; } public override Boolean TryInvokeMember(InvokeMemberBinder binder, Object[] args, out Object result) { MethodInfo method = FindMethod(binder.Name, args.Select(a => a.GetType()).ToArray()); if (method == null) { result = null; return false; } result = method.Invoke(null, args); return true; } private MethodInfo FindMethod(String name, Type[] paramTypes) { return m_type.DeclaredMethods.FirstOrDefault(mi => mi.IsPublic && mi.IsStatic && mi.Name == name && ParametersMatch(mi.GetParameters(), paramTypes)); } private Boolean ParametersMatch(ParameterInfo[] parameters, Type[] paramTypes) { if (parameters.Length != paramTypes.Length) return false; for (Int32 i = 0; i < parameters.Length; i++) if (parameters[i].ParameterType != paramTypes[i]) return false; return true; } private FieldInfo FindField(String name) { return m_type.DeclaredFields.FirstOrDefault(fi => fi.IsPublic && fi.IsStatic && fi.Name == name); } private PropertyInfo FindProperty(String name, Boolean get) { if (get) return m_type.DeclaredProperties.FirstOrDefault( pi => pi.Name == name && pi.GetMethod != null && pi.GetMethod.IsPublic && pi.GetMethod.IsStatic); return m_type.DeclaredProperties.FirstOrDefault( pi => pi.Name == name && pi.SetMethod != null && pi.SetMethod.IsPublic && pi.SetMethod.IsStatic); } } private static class StaticTestType { public static String Method(Int32 x) { return x.ToString(); } #pragma warning disable 649 // 忽略警告 字段永远不会被赋值给,并且总是有它的默认值 public static DateTime Field; #pragma warning restore 649 public static Guid Property { get; set; } } private static void DynamicStaticInvocations() { dynamic staticType = new StaticMemberDynamicWrapper(typeof(String)); Console.WriteLine(staticType.Concat("A", "B")); //动态调用String 的静态方法 staticType = new StaticMemberDynamicWrapper(typeof(StaticTestType)); Console.WriteLine(staticType.Method(5)); staticType.Field = DateTime.Now; Console.WriteLine(staticType.Field); staticType.Property = Guid.NewGuid(); Console.WriteLine(staticType.Property); } } private static void ExcelAutomation() { #if ReferencingExcel // Microsoft.Office.Interop.Excel.dll var excel = new Microsoft.Office.Interop.Excel.Application(); excel.Visible = true; excel.Workbooks.Add(Type.Missing); ((Range)excel.Cells[1, 1]).Value = "Text in cell A1"; // Put a string in cell A1 excel.Cells[1, 1].Value = "Text in cell A1"; // Put a string in cell A1 #endif } } //////////////////////////////// End of File //////////////////////////////////
标签:math generic amp false 部分 [] eof efault form
原文地址:https://www.cnblogs.com/eric-yuan/p/10218599.html