zoukankan      html  css  js  c++  java
  • c# 基础知识

    tuple元组

    赋值

      List<Tuple<string, int>> cc = new List<Tuple<string, int>>()
                {
                    new Tuple<string, int>("满减5", 1),
                    new Tuple<string, int>("满减2", 2),
                    new Tuple<string, int>("满减5", 3),
                    new Tuple<string, int>("满减1", 4)
                };

     取值

    foreach (var item in cc)
      {
            string ite = item.Item1;
             int ctNum = item.Item2;
      }

     new 关键字

    1、new 运算符:用于创建对象和调用构造函数。
    2、new 修饰符:用作修饰符时,new 关键字可以显式隐藏从基类继承的成员。
    3、new 约束:用于在泛型声明中约束可能用作类型参数的参数的类型。

    new关键字在我们的程序中可谓是无时不刻在用到,那么new关键字都可以用在哪些地方呢?考虑以下几个问题:

    1、new一个class对象和new一个struct或者new一个enum有什么不同?

      new一个class时,new完成2个内容:一是调用new obj命令为实例在托管堆中分配内存,二是调用构造函数实现对象初始化。

      new一个struct时,new运算符用于调用其构造函数,完成实例的初始化。

    2、new在.NET中除了创建对象实例外,还可以做什么?

      new关键字:作为运算符可以创建对象和调用构造函数;

      作为修饰符可以用于向基类成员隐藏继承成员,实现派生类中隐藏基类的virtual方法,不能和override共存;

      作为约束可以在泛型声明中约束可能用作类型参数的参数类型,即new约束指定泛型类声明中的任何类型参数都必须要有公共的无参构造函
    数;

      使用new关键字实现多态。

    3、new运算符可以重载吗?

      new运算符不可以重载。

     4、泛型中new关键字的作用?

      new运算符用于返回一个引用,指向系统分配的托管堆的内存地址,new分配内存失败,将引发OutOfMemoryException异常。

    5、new一个继承下来的方法和override有什么区别?

      new是隐藏基类方法,override是覆写基类方法。如果要访问new隐藏了的基类成员需要使用base关键字实现。

        隐藏和重写基类方法的异同

        1:方法重写:就是在基类中的方法用virtual关键字来标识,然后在继承类中对该类进行重写(override),这样基类中的方法已经
    被重写了,已经失去了功能了。当让基类的对象的引用直接指向继承类的对象时(多态性),调用该方法则是调用的继承类的方法。

        2:方法隐藏:无论基类中的方法是否用了virtual关键字,继承类中都可以用new关键字(如果不用new的话,不会产生错误,但会生
    成一个编译警告)将基类中的方法隐藏,所谓隐藏就是隐藏,不像重写,重写就是原来的(基类中)已经不存在了,而隐藏是原来的还存在。
    所以当让基类的对象的引用直接指向继承类的对象时(多态性),调用该方法则是调用的基类的方法。

    6、int i和int i = new int()有什么不同?

      new一个int时,new运算符用于初始化其值为0,使构造函数完成更优越的初始化操作。

    通过继承隐藏名称采用下列形式之一:

    •引入类或结构中的常数、指定、属性或类型隐藏具有相同名称的所有基类成员。

    •引入类或结构中的方法隐藏基类中具有相同名称的属性、字段和类型。 同时也隐藏具有相同签名的所有基类方法。

    •引入类或结构中的索引器将隐藏具有相同名称的所有基类索引器。

    指针

    指针在CC++里面可是一个好东西,但是到java,.net的时代指针已经被封装起来,对用户不可见,这点java做的非常的彻底。.net可能因为还
    存在一个托管C++,因此指针并没有完全废除,C#还是保留了指针的操作。


    要使用指针首先要对使用指针的代码用unsafe进行进行声明,声明和public声明一样,可以对整个类进行声明,也可以是类里面某个方法或者
    属性。在代码里什么后,还需要修改工程项目的Build属性,让编译器支持指针的操作。
    public
    unsafe partial class pointer : Form

    做好事前的工作就可以使用指针了。指针的使用方法和C++下使用没有太多差别。只要编译器不报错就没有太大问题。

    下面是对指针的一些使用上的理解:
    1.
    指针类型可以是实体变量(int,double)也可以是enum,同时也支持结构体变量struct。但不能是类。不过空指针可以指向类,只不过空指针
    不能进行任何操作,也只能把空指针作为传递对象来使用。
    2.
    C#提供一个的关键字stackalloc用于申请堆栈内存。注意,这个申请内存分配的是栈内存,当函数执行完毕后,内存会被自动回收。不过我想
    用这个栈内存基本可以解决40%的问题,而且使用的时候不必担心内存泄漏问题。
    3.
    .net 好像不直接支持堆内存的申请(这个对.net来说很危险),不过我们可以通过调用win32 api
    的方法进行申请。这样就可以解决剩下40%的问题。堆内存申请的方法在MSDN里面有相关的文档。
    4.
    结构体是一个特殊的对象。他与类的定义就差一个关键字,使用方法也和类一样,可以定义属性,可以定义方法。但是在进行指针操作的时候
    双方就有很大的差别了。结构体可以通过sizeof()取得大小,大小与结构体里有多少实体变量有关,但是如果struck里定义了类的对象,或者
    指针,sizeof可能会编译不过(void*
    的空指针例外,不过需要在结构体声明处加上unsafe)。
    5.
    fixed关键字:fixed()会告诉垃圾收集器,类实例的某些成员有指向他们的指针,所以这些实例不能移动目前了解的不多,不过有一个很实用
    的例子可以让指针能够和.net里的数组进行交互操作:

        private void button1_Click(object sender, EventArgs e)
            {
                MyClass myObject = new MyClass();
                //不能创建指向类的指针,这是因为垃圾收集器不包含指针的任何信息,只包含引用的信息
                //大多数类都包含值类型的成员,可以为这些值类型成员创建类型成员创建指针,但需要一种特殊的语法
                fixed (long* pObject = &(myObject.X))
                fixed(float* fObject=&(myObject.F))
                {
                    this.label2.Text = pObject->ToString();
                    this.label2.Text += fObject->ToString();
                }
            }

    6: 指针的取地址操作 和C里面的一样

    7:一个使用指针的基于堆栈的高效数组举例:C#很容易使用数组,但是有一个缺点就是这些数组实际上都是对象,是System.Array的实例,因
    此数组只能存储在堆上,会增加系统的开销,而使用指针就可以做到,但只能用于一位数组

    值类型与引用类型

    他们最大的区别就是存储的位置不同,前者值类型存储在内存的堆栈中(一些书上面也说是【栈】),后者存储在内存堆中(一些书上面说是【堆】),栈中的内存不需要自己就行回收,内存堆中的数据需要.Net
    FrameWork 自己的内存清理机制进行回收。

    简单类型(包括int, long, double等)和结构(structs)都是值类型

    如果使用Ref/out
    ,则是按照引用传递,也就是说传递的是参数的引用,有点类型于c,c++中的指针变量。这样的话,在子函数中修改会改变被传入作为参数的值。

    对于值类型:
    如果不使用ref/out :则就是普通的值传递,在c,c++中类似比较普遍。
    如果使用Ref/out,则是按照引用传递,也就是说传递的是参数的引用,有点类型于c,c++中的指针变量。这样的话,在子函数中修改会改变被传入作为参数的值。

    对于引用类型:

    如果不使用ref/out,那么实际上也是拷贝传递,但是注意,由于引用类型本身的就是一个对象的引用,这样传递的结果就是传入的参数在传入的时候,拷贝生成一个引用,这个引用也是指向参数引用指向的对象的。也就意味着两个引用指向同一个对象。

    如果使用Ref/out,那么实际上传递的是参数的引用,有点类型于c++中的指针的指针。很明显,实际上,还是同一个引用指向一个对象。

    实参与形参:
    形参:在定义函数中指定的参数就是形参,在未出现函数调用时,他们并不占内存中的存储单元,只有在发生函数调用时,函数中的形参才被分配内存单元。在调用结束后,形参所占的内存单元也被释放。
    实参:实参可以是常量、变量和表达式,但要求有确定的值。在调用时将实参的值赋给形参。在内存中,实参单元和形参单元是不同的单元。在调用函数时,给形参分配存储单元,并将实参对应的值传递给形参,调用结束后,形参单元被释放,实参单元仍保留原值。

  • 相关阅读:
    取出某块内存的二进制数据
    拷贝构造函数的第一个参数必须是自身类类型的引用
    大小端,memcpy和构造函数
    类型装换和内存数据显示
    ERROR: iterator not incrementable || iterator not decrementable
    什么时候删除指针后,要给指针赋NULL
    chapter11、4concurrent.future模块
    chapter11、3多进程 multiprocessing
    chapter8.3、二分查找
    chapter8.2、面向对象三要素--继承
  • 原文地址:https://www.cnblogs.com/fer-team/p/8000079.html
Copyright © 2011-2022 走看看