码迷,mamicode.com
首页 > 其他好文 > 详细

08 方法

时间:2015-03-20 18:29:49      阅读:179      评论:0      收藏:0      [点我收藏+]

标签:

本章主要讲了 名字是方法,却主要讲了构造器

 

实例构造器,静态构造器,在结构和类中的区别

 

生成了一样的代码,就算你不写构造器,编译器也默认生成一个

1     public class ClassTest
2     {
3         public ClassTest()
4             : base()
5         { 
6         
7         }
8     }
public class ClassTest
{ 
    
}
1   // 代码大小       7 (0x7)
2   .maxstack  8
3   IL_0000:  ldarg.0
4   IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
5   IL_0006:  ret

 

调用顺序.

 1     public class ClassTest
 2     {
 3 
 4         public int a;
 5         public int b = 5;
 6 
 7         public ClassTest()
 8             : base()
 9         {
10             a = 2;
11             b = 4;
12         }
13     }
  // 代码大小       28 (0x1c)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  ldc.i4.5
  IL_0002:  stfld      int32 EFTest.ClassTest::b
  IL_0007:  ldarg.0
  IL_0008:  call       instance void [mscorlib]System.Object::.ctor()
  IL_000d:  ldarg.0
  IL_000e:  ldc.i4.2
  IL_000f:  stfld      int32 EFTest.ClassTest::a
  IL_0014:  ldarg.0
  IL_0015:  ldc.i4.4
  IL_0016:  stfld      int32 EFTest.ClassTest::b
  IL_001b:  ret

 

先赋值.

然后在实例构造. 然后再赋值.

如果不没赋值,编译器会赋默认值,引用类型 NULL,值类型0.

 

值类型构造器

首先结构不允许 参数为空的构造器。编译器也不会创建默认构造器

1     public struct ClassTest1
2     {
      //错误 1 结构不能包含显式的无参数构造函数 
3 public ClassTest1() 4 { 5 6 } 7 }

 

在没有显示声明的构造器的情况下也编译器也不会声明

1     public struct ClassTest1
2     {
3 
4     }

技术分享

 

调用的顺序和 CLass一样 。同样没有初始化 总是被初始化为0或null

 

结构不允许默认构造函数。

结构中不能有实例字段初始值设定项.

1 private Int32 m_x = 5;

 

包括构造函数必须所有参数都赋值,不能部分赋值

 1     public struct ClassTest1
 2     {
 3         private Int32 m_x ;
 4         private Int32 m_y ;
 5 
 6         public ClassTest1(int x)
 7         {
 8             m_x = x;
 9         }
10     }

错误 1 在控制返回到调用方之前,字段“EFTest.ClassTest1.m_y”必须完全赋值

这些让我没有明白.

书中的说法是 "生成可验证的代码" 完全没有明白. 毕竟你完全可以这样

1     public struct ClassTest1
2     {
3         private Int32 m_x ;
4         private Int32 m_y ;
5     }
6 
7 var o = new ClassTest1();
8 Console.WriteLine(o.m_x);

 

然后输出为 0 这不也赋值了吗? 为什么就不能不分赋值.

不允许无参构造和内联赋值.也不是特别明白.

这种不知道的感觉特别蛋疼

 

 

静态构造器

首先静态构造器相当于一个私有且无参的实例构造

 1     struct ClassTest1
 2     {
 3         Int32 m_x ;
 4         Int32 m_y ;
 5 
 6         static ClassTest1()
 7         { 
 8         
 9         }
10     }

 

 

 1     public class ClassTest2
 2     {
 3         public static int staticcount = 0;
 4         public static int count = 0;
 5         static ClassTest2()
 6         {
 7             staticcount++;
 8             Console.WriteLine(" 静态构造调用 " + staticcount + "");
 9         }
10 
11         public ClassTest2()
12         {
13             count++;
14             Console.WriteLine(" 构造调用 " + count + "");
15         }
16     }

 

1 var o = new ClassTest2();
2 var o1 = new ClassTest2();
3 var o2 = new ClassTest2();
4 Console.WriteLine(o1.GetType());
5 Console.WriteLine(o2.GetType());
6 Console.WriteLine(o2.GetType());

技术分享

静态构造只调用了一次,而普通构造函数却能够每次初始化都调用.

上图也说明了调用顺序问题

此外,静态构造函数也只是由 CLR调用. 开发人员是无法调用的

 

关于性能损耗.

 1     public sealed class TypeConstructorPerformance
 2     {
 3         public static void Go()
 4         {
 5             const Int32 iterations = 1000 * 1000 * 1000;
 6             PerfTest1(iterations);
 7             PerfTest2(iterations);
 8         }
 9 
10         internal sealed class BeforeFieldInit
11         {
12             public static Int32 s_x = 123;
13         }
14 
15         internal sealed class Precise
16         {
17             public static Int32 s_x;
18             static Precise() { s_x = 123; }
19         }
20 
21         private static void PerfTest1(Int32 iterations)
22         {
23             Stopwatch sw = Stopwatch.StartNew();
24             for (Int32 x = 0; x < iterations; x++)
25             {
26                 BeforeFieldInit.s_x = 1;
27             }
28             Console.WriteLine("PerfTest1: {0} BeforeFieldInit", sw.Elapsed);
29 
30             sw = Stopwatch.StartNew();
31             for (Int32 x = 0; x < iterations; x++)
32             {
33                 Precise.s_x = 1;
34             }
35             Console.WriteLine("PerfTest1: {0} Precise", sw.Elapsed);
36         }
37 
38         private static void PerfTest2(Int32 iterations)
39         {
40             Stopwatch sw = Stopwatch.StartNew();
41             for (Int32 x = 0; x < iterations; x++)
42             {
43                 BeforeFieldInit.s_x = 1;
44             }
45             Console.WriteLine("PerfTest2: {0} BeforeFieldInit", sw.Elapsed);
46 
47             sw = Stopwatch.StartNew();
48             for (Int32 x = 0; x < iterations; x++)
49             {
50                 Precise.s_x = 1;
51             }
52             Console.WriteLine("PerfTest2: {0} Precise", sw.Elapsed);
53         }
54     }

 

 

这是书中一个例子

技术分享

同样的例子 我和书中得出的结果是不一样的. 不知道是不是CPU进化的结果导致的.

直接内联构造和静态构造 性能还是有些差别的。

不过这种调用次数这种差别。 我觉得可以忽略了...

 

接下来就是一些操作符以及自己写语法糖的介绍, 比较简单,贴一下代码就可以了

操作符重载

 1  internal sealed class Complex
 2     {
 3         public Int32 a;
 4 
 5         public Complex(Int32 c)
 6         {
 7             a = c;
 8         }
 9 
10         public static Complex operator%(Complex c1,Complex c2)
11         {
12             var c3 = new Complex(c1.a + c2.a);
13             
14             return c3;
15         }
16     }

 

 1 .method public hidebysig specialname static 
 2         class EFTest.Complex  op_Modulus(class EFTest.Complex c1,
 3                                          class EFTest.Complex c2) cil managed
 4 {
 5   // 代码大小       21 (0x15)
 6   .maxstack  2
 7   .locals init ([0] class EFTest.Complex c3)
 8   IL_0000:  ldarg.0
 9   IL_0001:  ldfld      int32 EFTest.Complex::a
10   IL_0006:  ldarg.1
11   IL_0007:  ldfld      int32 EFTest.Complex::a
12   IL_000c:  add
13   IL_000d:  newobj     instance void EFTest.Complex::.ctor(int32)
14   IL_0012:  stloc.0
15   IL_0013:  ldloc.0
16   IL_0014:  ret
17 } // end of method Complex::op_Modulus

 

 

 

1 var c1 = new Complex(1);
2 var c2 = new Complex(2);
3 Console.WriteLine((c1 % c2).a);
 IL_0000:  ldc.i4.1
  IL_0001:  newobj     instance void EFTest.Complex::.ctor(int32)
  IL_0006:  stloc.0
  IL_0007:  ldc.i4.2
  IL_0008:  newobj     instance void EFTest.Complex::.ctor(int32)
  IL_000d:  stloc.1
  IL_000e:  ldloc.0
  IL_000f:  ldloc.1
  IL_0010:  call       class EFTest.Complex EFTest.Complex::op_Modulus(class EFTest.Complex,
                                                                       class EFTest.Complex)

 

 

具体有哪些操作.

技术分享

技术分享

 

转换操作符方法

 1     public sealed class Rational
 2     {
 3         public Rational(Int32 num)
 4         {
 5             Console.WriteLine(num);
 6         }
 7 
 8         public static implicit operator Rational(Int32 num)
 9         {
10             return new Rational(num);
11         }
12     }

 

Rational r1 = 1;

 

当然他也有反过来的操作 explicit.

 

扩展方法

 1     public static class StringExtensions
 2     {
 3         public static Int32 ToFuck(this String c)
 4         {
 5             if (c == null)
 6                 return -1;
 7 
 8             return c.Length * 15;
 9         }
10     }

 

有点儿像 js 中更改原形一样. 

默认返回一个自身.

 

以上这些方法都是让你语法更加简洁。

理论上不用这些都是可以用其他方法弄出来。

 

end

 

08 方法

标签:

原文地址:http://www.cnblogs.com/HeyTommy/p/4354126.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!