忽略基础知识点梳理

.NET中的静态与非静态

静态类 vs 普通类

静态类与普通类的区别有以下几点:

1)静态类无法实例化而普通类可以;

2)静态类只能从System.Object基类继承;普通可以继承其它任何非static和非sealed类,但也只能继承一个类;

3)静态类不能继承接口;普通类可以继承多个接口;

4)静态类只能包含静态成员;普通类可以包含静态和非静态成员;

5)静态类不能作为字段,方法参数和局部变量使用;普通类可以;

静态类的意义:

可以用静态类封装一组不与任何对象相关联的方法,如Math类,Console类。

静态构造函数 vs 实例构造函数

静态构造函数与实例构造函数的区别有以下几点:

1)静态构造函数属于类,在第一次用到该类时执行且只执行一次;实例构造函数属于对象,在每次初始化一个新对象的时候都会执行;

2)静态构造函数只能定义一次,且不能包含参数;实例构造函数可以定义重载,且可以包含参数;

3)静态构造函数只能访问类型的静态字段;实例构造函数可以访问类型的静态和非静态字段;

4)静态类不能包含访问修饰符,默认为private.

静态构造函数的意义:

设置类型的初始化,例如初始化类型需要的实例对象,为类型的静态字段赋值等。

静态方法 vs 实例方法

静态方法与实例方法的区别有以下几点:

1)静态方法属于类,通过类来调用;实例方法属于对象,通过对象来调用;

2)静态方法不能访问类的非静态成员;

静态方法的意义:

完成一个与特定对象无关的功能。

静态字段 vs 非静态字段

静态字段与非静态字段的区别:

静态字段属于类,通过类来调用;非静态字段属于对象,通过对象来调用。

静态字段的意义:

可以用静态字段来记录一些属于类本身的信息。

代码演示

复制代码
 1 public class Test
 2     {
 3         public int i = 10;
 4         public static int j = 20;
 5         public int k;
 6 
 7         public Test()
 8         {
 9             Console.WriteLine("i is a non-static field, its value is {0}", i);
10             Console.WriteLine("j is a static field, its value is {0}", j);
11         }
12 
13         public Test(int k)
14         {
15             this.k = k;
16             Console.WriteLine("i is a non-static field, its value is {0}", i);
17             Console.WriteLine("j is a static field, its value is {0}", j);
18             Console.WriteLine("k is a non-static field, its value is {0}", k);
19         }
20 
21         static Test()
22         {
23             Console.WriteLine("I am a static constructor, I couldn't contain any parameters!");
24             Console.WriteLine("I couldn't access to the non-static field i, I can only access to the static field j, the value of j is {0}", j);
25         }
26 
27         public void Print()
28         {
29             Console.WriteLine("I am a instance method, I can access both the non-static field and the static field!");
30             Console.WriteLine("The value of i is {0} and the value of j is {1}", i, j);
31         }
32 
33         public static void StaticPrint()
34         {
35             Console.WriteLine("I am a static method, I couldnt access to the non-static field i,  I can only access to the static field j, the value of j is {0}", j);
36         }
37     }
复制代码
复制代码
 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             Test t1 = new Test();
 6             Test t2 = new Test(30);
 7             
 8             Console.WriteLine(Test.j);
 9             Console.WriteLine(t1.i);
10             Console.WriteLine(t2.k);
11 
12             Test.StaticPrint();
13             t1.Print();
14             Console.Read();
15         }
16     }
复制代码

运行结果

从运行结果可以看出,在Main方法中创建了两个Test对象,静态构造函数只执行了一次,且先于实例构造函数执行,实例构造函数在两次实例化过程中各执行了一次。同时可以看到我们是通过Test.j来调用的j字段,而i字段和k字段的调用则通过Test的两个对象t1和t2调用。同样的,静态方法StaticPrint也是用Test类来调用,而实例方法Print通过Test类的对象来调用。

Fighting like Allen Iverson! Never never give up!
 
分类: C#

忽略基础知识点梳理

 今天打开一本《C#高级编程》值类型与引用类型翻看,发现有些熟悉的知识点跟以往认识很不一样,今天对某些忽略点的在认识做一些总结。以便深刻理解,倘若你也遇到过,以此共享!

预定义数据类型:

      这个里面有个重心点也是很多面试点就是值类型与引用类型。本人已多次总结,这里不再过多解释。那么我想关心什么是预定义类型?预定义类型多么?有多少呢?

       预定义类型是具有CTS标准规范的类型,他们并不内置在C#中,而是内置的.NET Framework中。其他类型都来源于预定义类型的继承。C#预定义类型一共有15个,其中值类型13个(sbyte,short,int,long,byte,ushort,uint,ulong)2个浮点类型(float,dpuble)和1个decimal型,1个bool型,1个字符型(char)和2个预定义引用类型(object,string),object父类毋庸置疑,但是string的引用类型就显得比较特殊了。

String引用类型有何特殊?

复制代码
        static void Main(string[] args)
        {

            string s1 = "hello Tom!";
            string s2 = s1;
           
            Console.WriteLine(s1);
            Console.WriteLine(s2);
            Console.Read();
         }
复制代码

输出结果1:

修改s1数据:

复制代码
        static void Main(string[] args)
        {

            string s1 = "hello Tom!";
            string s2 = s1;
            s1 = "New hello Tom!";
            Console.WriteLine(s1);
            Console.WriteLine(s2);
            Console.Read();
         }
复制代码

运行结果2:

很明显结果是不一致的。原因在于:

结果1:s1引用类型分配在堆中。s2对象指向s1地址索引这个没问题!相信大家都能理解,这个不在详细描述,随后咱们反汇编一下!

结果2:s1原先在堆分配内存中分配地址1(hello Tom!),现在对s1对象重新赋值。相当于new s1.那么堆自然会给s1分配新内存地址2(new hello Tom!).然而s2依旧指向地址1(hello Tom!)中.运行后自然结果不同。

      为了详细剖析咱们想想。根据结果不同,肯定s2的内存分配大小更大,而且在调用时s1和s2在第一次调用同一个地址,第二次肯定不同。我们的猜想对于不对?需要实际验证,调用两者反汇编代码:

IL1:

IL2:结果2地内存大小偏大,我们猜想一正确。IL_0009是加载新的string,我们验证没错。

下面了解下有关编译C#文件更多内容

      C#代码是托管代码我们所知道的。其原理就是c#代码经过相应的C#编译器(CSC.exe)编译的IL语言。这一点与C,C++,JAVA都是一样的,它们也同样对应相应编译器编译到IL。这里主要介绍C#编译器。其编译选项主要有哪些呢?

1./t:exe        输出控制台应用程序。

2,/t:library    输出带有清单(Il和元数据等)类库

3,/t:modult    输出没有清单的组件

4,/t:winexe    输出windows应用程序(么有控制台窗口)

具体使用:咱们以类库Librayry.cs文件为例。其经过生成后为Librayry.dll。命令编译为:csc /t:library Librayry.cs(同vs中生成一样效果)

控制台I/O问题,也许还有你所不知道的?

1,一个算法输出如下格式:1,空格会显示输出,{m,n}m是表示第m个索引一般0到m,n是宽度值

            int i=330;
            int j = 30;
            Console.WriteLine(" {0,4}\n+{1,4}\n-----\n {2,4}", i, j, i + j);
            Console.ReadKey();

2,带有美元符号控制格式输出

            decimal i=345.34m;
            decimal j = 76.7m;
            Console.WriteLine(" {0,9:C2}\n+{1,9:C2}\n-----------\n {2,9:C2}", i, j, i + j);
            Console.ReadKey();

3,也可以占位符表示:

            double d = 0.544;
            Console.WriteLine(" {0:#.00}", d);
            Console.ReadKey();

下面就介绍下C#预处理器指令吧!

      熟悉c与C++开发的预定义指令一定也不陌生,但是我开始学习C#时以为C#没有预定义概念,应该平常就不会用到它。其实这也正是其作为托管代码的原因所在,C#同样具有与预处理指令。就像内存分配一样,C#不需要手动分配,托管堆会自动分配(上面string分析中结果1的30个大小内存就是自动分配,记得吧?)预处理指令很好认,开头都是#

1,#define和#undef

这里的#define不是实际代码的一部分,只是告诉编译器它定义对象的存在。只在编译代码时存在

#undef,显而易见,这个就相当于删除定义啦

2,#if,#elif(else if),#else ,#endif

这里同样是成对存在的,使用方法与平常if语句一样,但是注意这里;代码演示吧!

这是粘贴出来的,原始定义debug,这里不存在,所有代码编译不会通过,代码部分为灰色。

 我强制拿一句Console.ReadKey();运行结果是空白:

3,#warning和#error

这个大家肯定非常熟悉,我们编译出错警告都会遇到,究竟怎么出现呢?原理是什么?

当编译器遇到它们两个会产生警告和错误。如果编译器遇到#warning时候,会显示其指令后面的代码,这个过程也是C#对应编译器实现的。然后继续往下运行。但是如果遇到#error会显示错误信息,立即退出编译,并且不会产生IL代码。即便查看也是没有的

4#region和#endregion

复制代码
  #region   预编译#If应用
#if debug
            double d = 0.544;
            Console.WriteLine(" {0:#.00}", d);
            Console.ReadKey();
#endif
            Console.ReadKey();
            #endregion
复制代码

点击节点

这个过程中编译器识别这对指令,可以让代码块折叠,更好代码布局和显示。这个过程中它们好像没有什么用,不影响编译过程。

C#编程规则异常重要!

C#规范编程,这样对于自己也是好的风格,思路清晰,让别人看起来也清晰明了。特别团队合作和别人维护都很重要!(个人总结几点)

1,命名空间异常重要,有时候可能在你都计算机可以,移植到另一台就命名冲突。故采用公司名/个人名.项目名称:如zhangsan.demo

2,私有变量头字母小写:如myTd

3,公用的或者保护类型:如MyId

4,必须字母或者下划线开头,可以追加数字:_myId

5,不能包含关键字,但是加@可以:如@int

6属性和方法尽可能让人能够一看即懂:如:SetPassword()


       到此,今天所看到的的细节问题基本总结完了。明天由于还要早起,暂时到这吧!

http://www.cnblogs.com/baiboy
 
分类: C#框架设计

框架设计

 
摘要: 今天打开一本《C#高级编程》值类型与引用类型翻看,发现有些熟悉的知识点跟以往认识很不一样,今天对某些忽略点的在认识做一些总结。以便深刻理解,倘若你也遇到过,以此共享! 预定义数据类型: 这个里面有个重心点也是很多面试点就是值类型与引用类型。本人已多次总结,这里不再过多解释。那么我想关心什么是预定义类型?预定义类型多么?有多少呢?阅读全文
posted @ 2013-03-26 22:54 卿君 阅读(452) | 评论 (2) 编辑
 
摘要: 在日常编码工作中,我们追求高效的代码。需要的是高性能可重用的代码,而非重复的代码。那么泛型则显得尤为方便.其显著的特点是重用代码,保护类型和提高性能.并且在泛型使用过程中减少装箱操作.泛型可以用途广泛,可根据需求创建泛型接口,泛型委托,泛型类,泛型方法,泛型集合.但是却不能创建泛型枚举!下面认识下什么是泛型,以及泛型有哪些类型和优点.最后依旧采用小实例的演练走进泛型的世界.阅读全文
posted @ 2013-03-22 22:29 卿君 阅读(8) | 评论 (0) 编辑
 
摘要: 接口,对于大家都不陌生,至于何时使用,怎么使用?这里举一个例子:假如一个类A,负责传输数据。而类B,恰好是接收数据。我们还需要一个类C用来接收和传输数据。那么怎么样让A类和B类继承C呢?有的编程语言,允许多继承。子类可以继承多个父类。但是在C#中,定义不能多继承,但是可以使用多个接口。那么要继承接口就需要interface定义它ID,内部可以封装方法,但是注意,倘若你要继承ID接口,那么接口内部的所有方法属性都要实现。说到此处,不免有人问:“接口和父类继承有何区别?”. 一般是泛类中的个体,即is--a的关系使用继承。如:狗是动物的一种可以使用,Class 狗:动物 而接口强调是对象具有某种能力,即can--do的关系使用接口。如:大雁会飞,Class 大雁:I飞 C#定义子类不许继承多个类,但是可以多个接口。如:唐老鸭是动物,它会说话,会游泳,Class 唐老鸭:动物,I说话,I游泳阅读全文
posted @ 2013-03-19 14:28 卿君 阅读(1074) | 评论 (2) 编辑
 
摘要: 【引子】宿主为什么在运行时发现插件的原因? 信息通常用于创建动态的可扩展性的应用程序。这种类型应用程序可以由一家公司构建宿主应用程序,其他公司可以创建插件以扩展宿主应用程序。宿主应用程序不可能在插件上构建和测试,因为插件有不同公司构建的,而且还极有可能在宿主应用程序发布后创建。阅读全文
posted @ 2013-03-10 10:50 卿君 阅读(57) | 评论 (0) 编辑
 
摘要: 认识什么是CLR寄宿和应用程序域? CLR寄宿:允许任何应用程序域使用CLR的特征。允许已有的应用程序至少局部使用托管代码编程,并为应用程序提供通过编程支持自定义和可扩展性的能力。 应用程序域:允许第三方信任的代码在已存在的进程中运行,并保证应用程序的数据结构,代码以及安全上下文不被利用或不遭受安全风险。 认识什么是CLR寄宿和应用程序域? CLR寄宿:允许任何应用程序域使用CLR的特征。允许已有的应用程序至少局部使用托管代码编程,并为应用程序提供通过编程支持自定义和可扩展性的能力。 应用程序域:允许第三方信任的代码在已存在的进程中运行,并保证应用程序的数据结构,代码以及安全上下文不被利用或不遭受安全风险。阅读全文
posted @ 2013-03-09 19:51 卿君 阅读(17) | 评论 (0) 编辑
 
摘要: 简述内存回收机制:应用程序调用new操作符创建对象时,在地址空间即托管堆不包含任何对象时,这时添加到托管堆上的对象称为第0代,第0代对象会被分被一个预算内存大小,假如256K,第0代对象假如有4个ABCD.并且AD为根.那么与AD有联系的所有对象都被CLR认可.当0代超出内存时,托管堆的NExtObjPtr指针地址开始对0代中的非根(BC对象)标记.然后将其清除.D对象内存将压缩.产生AD连续分配的内存,此时,该片段内存已经成为第1代.重新分配对象即为第0代,以此类推,垃圾回收由浅入深,即从0代到第3代(总共3代).这时当托管堆的内存满时.才需要执行垃圾收集,垃圾收集总共三种方式分别是:Dispose方法,Close方法和Finalize方法(不能显示调用,只能被碎片收集程序调用).以上为本人对垃圾回收机制总结,下面对重点问题剖析:阅读全文
posted @ 2013-03-07 21:23 卿君 阅读(26) | 评论 (0) 编辑
 
摘要: 在程序编译中,异常是难免不遇到的。针对异常合适的处理,可以使代码健壮性更强,便于开发维护,有利于性能提升等特点。还有以下优点: 1异常处理可以将资源文件代码放在一个指定的位置。如:try{}。。finally{}块中的代码 2异常处理可以将处理的代码放在一个集中位置。如:catch{}块。有时候导致代码的异常原因有:算术溢出,堆栈溢出,内存不足,参数越界,数组索引越界,资源已释放等。 3异常处理可以定位和修复代码中的bug。当代码发生故障时,公共语言运行库遍历线程的调用堆栈,查找能够处理的代码。阅读全文
posted @ 2013-03-06 15:39 卿君 阅读(44) | 评论 (0) 编辑
 
摘要: 检查是否安装NET Framework的两个方法1,可以检查%SystemRoot%\system32目录下是否有MSCorEE.dll文件,存在则表明已安装好,反之则安装不成功2,通过注册表项中检查小写字母v开头,后跟一个数字的子项(推荐)HKEY_LOCAL_MACHINE\SOFTWARE\MICROSOFT\.NETFramework\policy微软还提供CLRVer.exe命令行实用程序,理出一台机器上安装的所有CLR版本为了安全或满足其他要求,C#编译器提供/platform命令行开关项。控制不同版本的目标平台运行图例总结:公共语言运行库运行过程是相关进程的主线程调用MSCorE阅读全文
posted @ 2013-03-04 13:41 卿君 阅读(13) | 评论 (0) 编辑
 
摘要: 程序集讲一个可重用的,可保护的,版本控制的组件的逻辑及物理表示区分开编译器:生成一个清单和托管模块图示:总结:上节我们知道源代码生成托管代码,在此过程中会有相应的编译器将多个托管代码和源文件合并成一个程序集的过程.最终生成一个程序集.阅读全文
posted @ 2013-03-04 13:28 卿君 阅读(13) | 评论 (0) 编辑
 
摘要: CLR:由多种不同编程语言使用的运行库托管模块:中间语言和元数据非托管语言:C/C++,不过此为特殊,可以写成托管代码托管语言:C#托管模块1,PE32/PE32+头:PE32运行在win32位系统中,win32+运行在64位系统2,CLR头,包括CLR版本,方法入口main,元数据标记,元数据,资源,名称3,IL代码:CLR将IL编译成本地cpu指令图:总结:在net的CLR(公共语言运行库)中包括托管语言(C#)和非托管语言(例如C++),两者到底什么区别.下面以数组为例C#初始化数组不必考虑内存分配问题,如果你用反汇编工具可以看到IL代码,会自动分配内存大小C++则与此不同,你需要事前分阅读全文
posted @ 2013-03-04 13:18 卿君 阅读(9) | 评论 (0) 编辑
原文地址:https://www.cnblogs.com/Leo_wl/p/2983971.html