美文网首页C#学习的心得笔记
刘铁猛C#(6)——类型,变量与对象详解(上)

刘铁猛C#(6)——类型,变量与对象详解(上)

作者: 北欧的蓝天 | 来源:发表于2019-10-22 07:01 被阅读0次

    类型

    就是数据类型,数据结构其实就是数据类型的一个延伸。

    1)数据类型就是一系列性质相同的值的集合,并对它们进行有效的表达。可见,数据类型来源于生产实践,不是凭空想象出来的。

    2)数据类型配备了一系列与之相配套的操作。可见,某些操作是专门针对某一类数据类型的,不能混用。

    3)数据类型,可以看成数据的“型号”,有不同的size。

    计算机硬件系统分为运算器,控制器,存储器和I/O系统。

    运算器+控制器:CPU

    存储器:内存。程序要运行,必须要从硬盘加载到内存中才能运行。内存就是程序运行的空间。

    数据类型(数据型号),指数据在内存中所占的空间。

    好的程序员要考虑程序运行时的内存使用是否合理,有没有浪费内存,有没有出现内存泄漏(内存空间不能被释放)等等内存问题。

    内存浪费,一是浪费硬件投资,二是挤占其他程序所需的内存空间,拖慢系统。程序性能不好。

    扩展存储器:如硬盘,程序不运行时,就放在扩展存贮器中。即便断电,数据也不会丢。

    启动一个程序快,要求内存大,硬盘快。

    编程语言的数据类型和数学中的数据类型,大多数情况下一样,有时会有显著区别。

    e.g. 数学中 :int 3 / int 4 = 0,75.

    编程中,int 3 / int 4 = 0. 因为配备给整数的运算方法和配备给小数的运算方法不一样,整数运算的答案也要是int(在操作符部分会详解)。

    编程语言分为

    1)强类型(受数据类型约束很强),如:C#

    长整型赋值给整型的变量,会报错。以此保证数据的完整性和安全性。

    不允许类型的混用,保证了数据的正确性

    C语言的强弱性没有C#强。C语言中,整型和bool是混用的,if判断条件只要不是0,都是true。

    C#为了模仿弱类型的灵活性,引入了动态类型dynamic

    //用dynamic可以获得类似Javascript在类型上的灵活性

                dynamic myVar = 100;

                Console.WriteLine(myVar);

                myVar = "Mr.Okay!";

                Console.WriteLine(myVar);

     2)弱类型(不怎么受数据类型的约束),如:Javascript, 基本上不受数据类型的约束,很灵活,但是优点也是缺点,很容易把逻辑弄乱。写C和Javascript,一定要注意数据类型。

    <!DOCTYPE html>

    <html>

    <head>

        <meta charset="utf-8" />

        <title></title>

        <script>       

            function ButtonClicked()

                {

                var myVar = 100;

                myVar = "Mr.Okay";

                alert(myVar);

            }

        </script>

    </head>

    <body>

        <h1> Hello Javascript! </h1>>

        <input type="button"value="Click Me"onclick="ButtonClicked()"/>

    </body>

    </html>

    类型系统非常重要,有很多相关面试题。

    1)sbyte,带正负号,由于带符号,所以要用最高一位来给正负号。

    2)byte,不带正负号

    3)Char,Unicode16位,能放65535个字节,对于全世界的大多数语言都够用了。Unicode中收入的常用汉语也就几千个字符。

    4)short,有正负号的短整型,若一个数字的范围在-32768 --- +32768之间,用一个短整型代表就行了,不会占用过多的内存空间。

    5)ushort,无正负号的短整型。

    6)int 带正负号的整型,32位,-2147483648 --- +2147483648。比方说某个幼儿园的孩子,数目不超过200,用一个短整型ushort表示就够了,不需要用int。

    7)uint,32位,无正负号的整数,0 --- 4294967295

    8)long,64位,带正负号的长整型。

    9)ulong,64位,不带正负号的长整型。一般用于大型系统中,表示身份ID,长度足够用了。

    float,可以精确到~6-9位小数。

    基类型(BaseType也叫“副类型”)

    在面向对象设计中,被定义为包含所有实体共性的class类型,被称为“基类”。

    一个类型可以知道自己的基类型是谁,在整个继承链上,位于什么位置。两大作用:

    1) 静态作用

    非静态的类成员,就是实例成员。

    一个程序在没有执行的时候,就是程序的静态时期,即:编辑期和编译期(build)。静态分析程序。

    如:写好一段代码,其中需要访问一些类型的成员(变量,实例等),用编译器编译它,此时依然是静态期,此时编译器可以用所要访问的类型,去检验代码,如果有误,编译器直接报错。保证了程序的正确性。

    2)动态作用

    一个程序在执行起来后,就是程序的动态时期,即:运行期。动态调试程序。

    C#的反射技能(高级技能),给定一个类型或对象,可以立即知道其中有哪些成员,并根据需要来操作这些成员。e.g. 

               Type myType = typeof(int);

                Console.WriteLine(myType.Name);                  //类型名称

                Console.WriteLine(myType.FullName);            //类型全名

                Console.WriteLine(myType.BaseType);           //基类

                Console.WriteLine(myType.BaseType.BaseType.FullName);         // 基类的基类

    e.g.      Type myType = typeof(FormatException);

                PropertyInfo[] pInfos = myType.GetProperties();

                foreach (var p in pInfos)

                {

                    Console.WriteLine(p.Name);

                }

    //打印出FormatException的 Properties。

                Console.WriteLine(myType.Name);                 //类型名称

                Console.WriteLine(myType.FullName);            //类型全名

                Console.WriteLine(myType.BaseType);          //基类

                Console.WriteLine(myType.BaseType.BaseType.FullName);        // 基类的基类

    //打印出FormatException的 Methods。

    MethodInfo[] mInfos = myType.GetMethods();

                foreach (var m in mInfos)

                {

                    Console.WriteLine(m.Name);

                }

    类型的运算

    e.g. 

    double result = 3.0 / 4.0;

    Console.WriteLine(result);   // 结果为0.75

    double result = 3 / 4;

    Console.WriteLine(result);   // 结果为0,3和4是整型,运算结果也为整型,即便有double。

    可见,数据类型知道自己该进行什么运算。如果是整型,除法的结果就是取整。

    程序运行时,变量在内存的存贮

    1. Stack 栈:内存分为堆和栈。

    用于调用方法,比较小,一般只有几兆

    2. Stack overflow:栈溢出

    栈比较小比较快,但是会爆掉。如果:

    a)算法没写好,函数调用过多,会涨爆。

    b)程序有错误,分配了过多的内存,也会爆。

    e.g 1.  下列程序,方法自己调用自己,只递不归,无限循环下去,就会撑爆栈,导致栈溢出。

    class BadGuy

            {

                public void BadMethod()

                {

                    int x = 100;

                    this.BadMethod();

                }

            }

    static void Main(string[] args)

            {

                BadGuy bg = new BadGuy();

                bg.BadMethod();

           }

    e.g 2. 直接到栈上切内存,只要切大了,栈就会爆掉,导致栈溢出。

    unsafe 

                {

                    int* p = stackalloc int[99999999];

                }

    3. Heap 堆

    存放对象和实例,比较大,可以有几个G

    4. 使用Performance monitor查看进程的内存使用量

    e.g.

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Threading.Tasks;

    using System.Windows;

    using System.Windows.Controls;

    using System.Windows.Data;

    using System.Windows.Documents;

    using System.Windows.Input;

    using System.Windows.Media;

    using System.Windows.Media.Imaging;

    using System.Windows.Navigation;

    using System.Windows.Shapes;

    namespace Liu6HeapSample

    {

        /// <summary>

        /// Interaction logic for MainWindow.xaml

        /// </summary>

        public partial class MainWindow : Window

        {

            public MainWindow()

            {

                InitializeComponent();

            }

            List<Window> winList;

            private void Button_Click(object sender, RoutedEventArgs e)

            {

                winList = new List<Window>();

                for (int i = 0; i < 15000; i++)

                {

                    Window w = new Window();

                    winList.Add(w);

                }

            }

            private void Button_Click_1(object sender, RoutedEventArgs e)

            {

                winList.Clear();

            }

        }

    }

    Build编译上述代码。Build指编译自己的代码,以便和其他的代码组件“组装”在一起。build就是“组装”。软件工程师有个分支,叫build工程师,就是专门给大型软件做build。

    右键点击,选中Open Folder,bin\Debug下有个应用程序。双击程序,使其从硬盘加载到内存中,开始执行之后,就形成一个进程。也就是这个程序正在运行的一个实例。程序运行起来后,会产生一个同名的进程,进程还会有进程ID,简称为pID(process id)。

    windows+r,打开运行窗口,输入perfmon

    打开性能监视器

    5. 内存泄

    堆不会爆掉,但是在堆里分配了很多对象,最后忘了回收这些对象,浪费内存,称作“内存泄漏”。

    C++需要手动释放内存。

    c#有内存垃圾收集器,会自动回收不用的内存。C#不容易出现内存泄漏。相对安全很多。

    6.总结:类型在C#中的作用

    变量都有自己的类型,程序会根据变量类型,将变量分配到堆或者栈(注意:实例永远放在堆里)。

    相关文章

      网友评论

        本文标题:刘铁猛C#(6)——类型,变量与对象详解(上)

        本文链接:https://www.haomeiwen.com/subject/tqfgmctx.html