找回密码
 立即注册
快捷导航

[C#] 查漏补缺

[复制链接]
茎肛互撸娃 2023-7-31 20:28:58 | 显示全部楼层
本帖最后由 茎肛互撸娃 于 2023-7-31 20:31 编辑

16种预定义类型

11种数值类型
整型:

  1. sbyte 8
  2. byte 8
  3. short 16
  4. ushort 16
  5. int 32
  6. uint 32
  7. log 64
  8. ulong 64

浮点:decimal、float、double

unicode字符类型char

bool

3种非简单类型
string,它是0个或多个Unicode字符所组成的序列(字符数组)。
object,它是所有其他类型的基类(包括简单类型)
dynamic,使用动态语言编写的程序集时使用。

用户自定义的类型
类类型 class
结构类型 struct
数组类型 array
枚举类型 enum
委托类型 delegate
接口类型 interface

程序运行时数据保存在内存中,保存数据的内存区域为:栈 和 堆
栈:内存数组,后进先出
堆:内存区域,在堆里分配大块的内存用于存储某种类型的数据对象。

值类型:byte/short/int/long/bool/struct/enum
引用类型:float/double/char/decimal/object/string/dynamic/class/interface/delegate/array

int a=1,b=2,c=3;

访问修饰符

  1. private
  2. public
  3. protected
  4. internal
  5. protected internal

常量 const

const int a = 1;
const double PI = 3.1416;

引用参数 ref
必须在形参和实参中都使用ref修饰符
实参必须是变量,且在作用实参前必须被赋值

void func1(ref int val){...}
int y = 1;
func1(ref y);      // 必须是变量

输出参数 out

void func1(out int val){...}
int y = 1;
func1(out y);      // 必须是变量

参数数组

void func1(int a, params int[] b){...}
func1(22, 10, 11, 33);

方法重载
一个类中可以有多个同名方法;
条件:必须有一个和其他方法不同的签名;
fun1(int a, int b)   这就是签名

命名参数

func1(int a, int b, int c){...}
func1(c:2, a:5, b: 3);

静态字段

class A{
    int b;  // 实例字段
    static int c;  // 静态字段
}

A.c;
或者 using static mynamespace;

静态字段被类的所有实例共享,所有实例都访问同一内存位置。因此,如果该内存位置的值被一个实例改变了,这种改变堆所有的示例都可见。
即使不存在类实例,静态成员也存在;

静态函数成员不能访问实例成员,但能访问其他静态成员。

成员常量 与 局部常量 的不同是:

void Main()
{
    Console.WriteLine(A.PI); // 可以使用
}

class A{
    public const double PI = 3.1416;  // 成员常量
}

对象初始化语句

public class Point{
    public int x { get; set; } = 1;
    public int y = 1;
}
new Point{x=5, y=6};

析构函数
执行在类的实例被销毁之前需要的清理或释放非托管资源的行为。非托管资源是指通过Win32API获得的文件句柄,或非托管内存块。使用.NET资源是无法得到它们的,因此如果坚持使用.NET类,就不需要为类编写析构函数。因此,等到第27章再介绍析构函数。

字段readonly
类似const

class A{
    readonly double PI = 3.1416;
    readonly int a;
    public A(){
        a = 5;
    }
}

this关键字

class A{
    int b = 10;
    public int fun1(int b){
        return this.b;
    }
}

索引器
索引器是一组 get和 set 访问器,与属性类似。
索引器和属性在很多方面是相似的。
和属性一样,索引器不用分配内存来存储。
索引器和属性都主要被用来访问其他数据成员,它们与这些成员关联,并为它们提供获取和设置访问。
属性通常表示单个数据成员。而索引器通常表示多个数据成员

class A{
    public string aa;
    public string bb;
    public string cc;

    public string this[int index]{
        set{
            switch(index){
                case 0: aa = value; break;
                case 1: bb = value; break;
                case 2: cc = value; break;
                default: throw new ArgumentOutOfRangeException("index");
            }
        }
        get{
            switch(index){
                case 0: return aa;
                case 1: return bb;
                case 2: return cc;
                default: throw new ArgumentOutOfRangeException("index");
            }
        }
    }

    // 索引器的重载
    public string this[int index, int index2]{
        ...
    }
}

var a = new A();
Console.WriteLine(a[0]);
回复

使用道具 举报

主题

0

回帖

1100

积分
 楼主| 茎肛互撸娃 2023-7-31 21:51:28 | 显示全部楼层
本帖最后由 茎肛互撸娃 于 2023-7-31 21:53 编辑

基类和派生类

所有的类都派生自object,不包括object自己;

单继承

一个类只能继承一个类,不能多继承,这种叫单继承;

屏蔽基类成员 new

用与基类成员名称相同的成员来屏蔽基类成员;

要屏蔽一个继承的数据成员,需要声明一个新的相同类型的成员,并使用相同的名称。

通过在派生类中声明新的带有相同签名的函数成员,可以屏蔽继承的函数成员。请记住,签名由名称和参数列表组成,不包括返回类型。

要让编译器知道你在故意屏蔽继承的成员,可使用new修饰符。否则,程序可以成功编译,但编译器会警告你隐藏了一个继承的成员。

也可以屏蔽静态成员。

class A{
    public string field1;
    public void fun1(int a){ ...}
}
class B: A{
    new public string field1;   // 用同样的名称屏蔽基类field1字段成员

    new public void fun1(int a){ ...}   // 用同样的名称和参数列表屏蔽基类fun1函数成员
}

基类访问 base

如果派生类必须访问被隐藏的继承成员,可以使用基类访问(baseaccess)表达式。

class A{
    public string field1;
}
class B: A{
    new public string field1;

    public void fun1(int a){
        Console.WriteLine(field1);        // 访问派生类的field1
        Console.WriteLine(base.field1);   // 访问基类的field1
    }
}

虚方法 virtual / override

可以使基类的引用访问“升至”派生类内。

class A
{
    // 虚方法
    virtual public void Print()
    {
        Console.WriteLine("A Print");
    }
}

class B : A
{
    // 覆写方法
    override public void Print()   // 派生类的方法和基类的方法要有相同的签名和返回类型
    {
        Console.WriteLine("B Print");
    }
}

void Main()
{
    B b = new B();
    A a = (A)b;     // 派生类强制转换为基类
    a.Print();      // 调用的是派生类B中的Print()
}
  • 覆写和被覆写的方法必须有相同的可访问性。
  • 不能覆写static方法或虚方法。
  • 方法、属性和索引器(前一章阐述过),以及另一种成员类型一一事件(将在后面阐述)都可以被声明为virtual和override。

访问修饰符

对类的访问修饰符

  • public  公开的,对任何程序集都可见
  • internal  内部的,仅在自己的程序集内可见

对成员的访问修饰符

  • public 很自由
  • private 只有其自己的类内部可见
  • protected 受保护的,自己的类内部和被派生的类可见,其他不可见,与是不是同一程序集无关
  • internal 同程序集内都可见,不同程序集都不可见,与继承不继承无关
  • protected internal 不同程序集也不是继承关系的不可见,其他都可见

抽象成员 abstract / override

是指设计为被覆写的函数成员。抽象成员有以下特征。

  • 必须是一个函数成员。就是说,字段和常量不能为抽象成员。
  • 必须用abstract修饰符标记。
  • 不能有实现代码块。抽象成员的代码用分号表示。

抽象成员只能抽象:方法、属性、事件、索引器;

abstract public void Print(string s);
abstract public int MyProperty {get; set;}

类似于虚成员,派生类中抽象成员的实现必须指定override修饰符。

抽象成员 和 虚成员 有什么区别?

  • 抽象成员:abstract,没有实现体,被分号取代,必须被覆写,使用override
  • 虚成员:virtual,有实现体,能被覆写,使用override

都只能作用方法、属性、事件和索引器;

抽象类

是指设计为被继承的类。抽象类只能被用作其他类的基类。

不能创建抽象类的实例。

抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带实现的成员的任意组合。

abstract class A{        // 抽象类不能实例化
    public void fun1(){

    }

    abstract public void func2();
}

class B: A{
    override public void func2(){

    }
}

任何派生自抽象类的类必须使用override关键字实现该类所有的抽象成员,除非派生类自己也是抽象类。

密封类 sealed

即禁止密封类被其他类继承

sealed class A{ ... }
   
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1楼
2楼
温馨提示

关于 注册码 问题

      由于近期经常大量注册机器人注册发送大量广告,本站开启免费入群领取注册码注册网站账号,注册码在群公告上贴着...

关于 注册码 问题

      由于近期经常大量注册机器人注册发送大量广告,本站开启免费入群领取注册码注册网站账号,注册码在群公告上贴着...

Archiver|手机版|小黑屋|DLSite

GMT+8, 2024-11-23 01:09

Powered by Discuz! X3.5 and PHP8

快速回复 返回顶部 返回列表