首页 > 其他分享 >第3章 创建类型

第3章 创建类型

时间:2022-11-11 16:25:57浏览次数:39  
标签:int 创建 class Method 类型 new public

3.1 类

class ClassName{
}

3.1.1 字段

字段是类或结构体中的变量成员。

  • static
  • public internal private protected
  • new (继承修饰符)
  • unsafe
  • readonly
  • volatile (线程访问修饰符)
    • 强迫使用的字段的读写操作都在代码指示的位置发生,而不是通过优化在其他位置生成。
static readonly int x=10,y=40;

3.1.2 方法

方法由一组语句实现某个行为。

表达式体方法

int Foo(int x){return x*2}

int Foo(int x)=>x*2;

void Foo(int x)=>Console.WriteLine(x);

方法重载

只要确保方法签名不同,可以在类中重载方法。(多个方法公用一个名称)

  • 方法的签名包括方法名和参数的个数和类型。

局部方法:在方法中允许定义另一个方法。

void Test(){
    int Foo(int x)=>2*x;
}

3.1.3 实例构造器

构造器执行类或结构体的初始化代码。

public class Test(){
    private int x;
    private int y;

    public Test(int x){
        this.x=x;
    }

    public Test(int x,int y):this(x){
        this.y=y;
    }

    // 解构器 方法名必须为Deconstruct,配合out参数使用
    public void Deconstruct(out  int x,out int y){
        x=this.x;
        y=this.y;
    }
}

// 解构器使用
var test=new Test(3,4);
(int a,int b)=test;
Console.WriteLine(a+" "+b);// 3 4

3.1.4 this 引用

this 引用仅在类或结构体的非静态成员中有效。

3.1.5 属性

属性和字段很像,但属性内部像方法一样含有逻辑。

public int Width {get;set;} = 120;

3.1.6 索引器

索引器为访问类或结构体中封装的列表或字典典型数据元素提供了自然的访问接口。

  • [ ]
class Sentence{
    string[] words="I am Bob";

    public string this[int wordNum]{
        get{return words [wordNum];}
        set{words [wordNum] =value;}
    }
}

// 使用索引器
Sentence s=new Sentemce();
Console.WriteLine(s[2]);// Bob
s[2]="Alice";
Console.WriteLine(s[2]);// Alice

3.1.7 常量

常量是一种值永远不会改变的静态字段。 const

3.1.8 静态构造器

每个类型的静态构造器只会执行一次,而不是每个实例执行一次。

  • 一个类只能定义一个静态构造器(名称与类名相同,并且没有参数)
class Test{
    static Test(){
    }
}

执行顺序:静态字段——>静态构造——>字段——>构造器

3.1.9 静态类

static 类只能包含静态成员,并且不能有子类。

3.1.10 终结器

终结器是只能在类中使用的方法。

  • 该方法在垃圾回收器回收未引用的对象占用的内存前调用。
class Test(){
    ~Test(){
    }
}

3.1.11 分部类型和方法

分部类型允许一个类分开在两个文件定义。

// Test1.cs
partial class Test{
}

// Test2.cs
partial class Test{
}

分部类中的分部方法(partial)一个声明,一个手动实现。

3.1.12 nameof 运算符

nameof 运算符返回任意符号的字符串名称(类型,成员,变量等)。

3.2 继承

类通过继承另一个类来扩展对自身进行扩展或定制。

3.2.1 类型转型

向上转型:创建一个基类指向子类的引用 (向上转型仅仅影响引用,不会影响被引用的对象)

Son son=new Son();

Parent parent=son;

向下转型:从基类引用创建一个子类的实现 (显示转换,可能出错)

Parent parent=new Parent();

Son son=(Son)parent;

 

is 和 as 运算符

is 运算符检查引用的转换是否能够成功,即对象是否从某个特定的类派生(或是实现某个接口)

if(a is TestClassName){
    Console.WriteLine((TestClassName)a);
}

// 等价代码

if(a is TestClassName t){
    Console.WriteLine(t);
}

is ⇒ 验证一个数据项是否属于特定类型。

as ⇒ 相比is 更进一步,尝试将对象类型转换为特定类型。如果类型不能转换,as操作符会返回null。

3.2.2 虚函数成员

提供特定实现的子类可以重写(override)标识为virtual 的函数。

  • 方法、属性、索引器和事件 都可以声明为virtual
public class A{
    public virtual int Method(int x){
        return 2*x;
    }
}

public class B:A{
    public override int Method(int x){
        return 3*x;
    }
}

3.2.3 抽象类和抽象成员

抽象类不能实例化,抽象类的子类必须实现所有抽象类的方法、属性等。 abstract

public abstract class A{
    public virtual int Method(int x);
}

public class B:A{
    public override int Method(int x){
        return 3*x;
    }
}

3.2.4 隐藏继承成员

父类和子类有相同的成员,那么子类的成员就会隐藏父类的成员。

public class A{
    public int x=1;
}

public class B:A{
    public int x=2;
}

// 编译器会发生警告。使用new 修饰符,阻止编译器发生警告。
public class B:A{
    public new int x=2;
}

new 和重写

public class Class1 {
    public virtual void Method() {
        Console.WriteLine("base 默认方式!");
    }
}

public class Class2 : Class1 {
    public override void Method() {
        Console.WriteLine("override 方式!");
    }
}

public class Class3 : Class1 {
    public new void Method() {
        Console.WriteLine("new 方式!");
    }
}

// 测试代码
Class2 class2=new Class2();
class2.Method();
Class1 class1 = class2;
class1.Method();

Class3 class3 = new Class3();
class3.Method();
Class1 class11 = class3;
class11.Method();

/* 测试结果:
    override 方式!
    override 方式!
    new 方式!
    base 默认方式!
*/

3.2.5 密封函数和类

函数和类可以使用 sealed 关键字 进行密封,防止被继承。

3.2.6 base 关键字

base 和this相近,作用:(1)从子类访问重写的基类函数成员(2)调用基类的构造函数

class B:A{
    public B(int x):base(x){
    }

    void Method(){
        Console.WriteLine(base.x);
    }
}

3.2.7 构造器和继承

子类必须声明自己的构造器。派生类可以访问基类的构造器,但并非自动继承。

如果子类的构造器省略base 关键字,那么基类的无参数构造器将被隐式调用。

构造器和字段初始化顺序:

public class A{
    int x=1;                       // 3rd
    public A(int x){
        ...                          // 4th
    }
}

public class B:A{
    int y=1;                       // 1st
    public B(int x):base(x+1){     // 2nd
        ...                          // 5th
    }
}

// 调用代码
B b=new B(3);

3.3 object 类型

3.3.1 装箱和拆箱

装箱:值类型实例 转换为 引用类型实例的行为。

拆箱:引用类型实例 转换为 值类型实例的行为。

int x=10;

// 装箱
string y=x;

// 拆箱
int z=(int)y;

3.3.2 GetType 方法和typeof 运算符

GetType() 运行时计算 —— 非静态的字段

typeof 编译时静态计算 —— 类

获取类型

3.3.3 ToString() 方法

所有内置类型都有此方法。

int x=10;

Console.WriteLine(x.ToString());

3.3.4 object 成员列表

 

3.4 结构体

结构体 与类相似,不同点:(1)结构体是值类型

(2)结构体不支持继承,除了隐式派生与System.ValueType

public struct Point{
    public int x;
    public int y;

    public Point(int x,int y){
        this.x=x;
        this.y=y;
    }
} 

// 调用
Point p1=new Point();
Point p2=new Point(2,3);
Console.WriteLine(p1.x + " " + p1.y);  // 0 0
Console.WriteLine(p2.x + " " + p2.y);  // 2 3

3.5 访问修饰符

3.6 接口

接口和类相似,但接口只为成员提供定义而不提供实现。

类是单继承,但可以多继承接口。

public interface IClass {
    void Method();
}

public interface IClass2 {
    void Method2();
}

public class Test:IClass,IClass2{
    public void Method(){
        Console.WriteLine("调用接口方法");
    }

    public void Method2(){
            Console.WriteLine("调用接口方法2");
    }
}

接口和装箱

interface IA{
    void Method();
}

struct S:IA{
    public void Method(){
    }
}

S s=new S();
s.Method();

IA ia=s;           // 装箱 struct(值类型)=>IA(引用类型)
ia.Method();

3.7 枚举

枚举类型是一种特殊的值类型,可以在枚举类型中定义一组命名的数值常量。

public enum States{
    Left,Right,Top,Bottom,
    LeftRight=Left | Right,
    TopBottom=Top  | Buttom,
    All=LeftRight  | TopBottom
}

// 使用枚举,默认int类型
States state=States.Left;

// 里面的类型设置为 byte 类型
public enum States:byte{
    Left,Right,Top,Bottom
}

// 枚举类型转换
byte x=(byte)States.Right;

// 枚举可以使用的运算符
=  ==  !=  <  >   <=  >=  +  -  ^  &  |  ~   +=  -=  ++  --  sizeof  

3.8 嵌套类型

嵌套类型是声明在另一个类型内部的类型。

public class A{
    public class B{
        public enum Colors{
            Red,Blue,Green
        }
    }
}

嵌套类的特征:

  • 可以访问它的外层类中的private成员,以及外层类能够访问的所有内容。

  • 可以在声明上使用所有的访问修饰符

  • 嵌套类型的默认可访问性是private而不是internal

  • 从外层类以外访问嵌套类型,需要使用外层类名进行限定(就像访问静态成员那样)

    A.B.Colors color=A.B.Colors.Red;

3.9 泛型

类似C++的模板。

3.9.1 什么是泛型?

public class Stack<T>{
    int position;
    T[] data=new T[100];
    public void Push(T obj) => data[position++]=obj;
    public T Pop() =>data[--position];
}

3.9.2 为什么需要泛型?

泛型是为了解决代码能够跨越类型复用而设计的。

3.9.3 泛型方法

使用泛型方法,许多基本算法就可以通用方式实现。

static void Swap<T>(ref T a,ref T b){
    T temp=a;
    a=b;
    b=temp;
}

// 使用
int x=4;
int y=5;
Swap<int>(ref x,ref y);

3.9.4 声明类型参数

// 泛型重载
class A{}
class A<T>{}
class A<T1,T2>{}

3.9.5 泛型的默认值

还是使用 default 关键字。 default(T)

3.9.6 泛型的约束

 

3.9.7 继承泛型类型

泛型类和非泛型类都可以派生子类。

class Stack<T>{
}

// 子类中仍可以令基类中类型参数都保持开放。
class SpecialStack<T>:Stack<T>{
}

// 子类可以用具体的类型来封闭泛型参数
class IntStack:Stack<int>{
}

// 子类型还可以引入新的类型参数
class List<T>{
}

class KeyedList<T,TKey>:List<T>{
}

3.9.8 自引用泛型声明

一个类型可以使用自身类型作为具体类型来封闭类型参数。

public interface IEquatable<T>{
    bool Equals(T obj);
}

public class Test:IEquatable<Test>{
    public string Color{get;set;}
    public int CC{get;set;}

    public bool Equals(Test t){
        if(t==null)
            return false;
        return t.Color==Color && t.CC==CC;
    }
}

// 第二种方式
class Foo<T> where T:IComparable<T>{}
class Bar<T> where T:Bar<T>{}

3.9.9 静态数据

 

3.9.10 协变

假定A可以转换为B,如果X<A>可以转换为X<B>,那么称X有一个协变类型参数。

  • 可变性(协变和逆变)不是自动的
  • 数组支持协变。如果B是A的子类,则B[]可以转换为A[](A和B都是引用类型)

声明协变类型参数:

// 假定Stack<T>类实现了IPoppable接口

public interface IPoppable<out T>{T Pop();}
//T上的out修饰符表明T只用于输出的位置(例如方法的返回值)
//out 修饰符将类型参数标记为协变参数
var bears=new Stack<Bear>();
bears.Push(new Bear());
IPoppable<Animal> animals=bears;
Animal a=anlmals.Pop();

3.9.11 逆变

假定A可以转换为B,如果X<B>可以转换为X<A>,那么称X有一个逆变类型参数。

public interface IPushable<in T>{
    void Push(T obj)
}

IPushable<Animal> animals=new Stack<Animal>();
IPushable<Bear> bears=animals;
bears.Push(new Bear());

 

标签:int,创建,class,Method,类型,new,public
From: https://www.cnblogs.com/Swbna/p/16880841.html

相关文章

  • 枚举创建范例
    packagecom.yeejoin.amos.boot.module.ugp.api.Enum;importlombok.AllArgsConstructor;importlombok.Getter;importjava.util.HashMap;importjava.util.Map;@......
  • DataLoader 每次迭代返回BatchEncoding还是dict类型依pytorch的版本而定
    发现DataLoader在不同的pytorch版本上,执行dataset的__item__会返回不同的效果。pytorch在1.12.1上,每一次迭代会返回BatchEncoding这个类型(可能会比这个版本低也......
  • String类型List排序
    一、升序:@Testpublicvoidtest1(){//创建ArrayList集合对象List<String>al=newArrayList<>();//往集合里添加数据al.add("aa");al.add("bb");......
  • Linux 创建交换(swap)分区
    20221111#创建交换文件sudoddif=/dev/zeroof=/swapbs=1MBcount=8192#验证交换文件大小sudodu-sh/swap#格式化文件为swap文件系统sudomkswap-Lswap......
  • 【Java】内存区域与对象创建
    这块内容是java很基础的部分,涉及到JVM的设计原理,很久以前就看到过,这次需要区分线程私有和共享基本java的运行时数据区可以分为五大块:程序计数器,为线程私有,每一个线程都有一......
  • struts2错误类型
    我们知道在http协议中,所有的参数都是String类型的,其实这些参数就是没有类型。那么从表单中得到的String数据怎么转换到程序中对应的数据类型呢?这其实是由Parameter拦截器实......
  • php 获取文件mime类型的方法
     php获取文件mime类型的方法 1.使用mime_content_type方法stringmime_content_type(string$filename)ReturnstheMIMEcontenttypeforafileasdeterminedb......
  • 判断一个变量的数据类型
    调用Object.prototype.toString.call()方法Object.prototype.toString.call('1')'[objectString]'Object.prototype.toString.call(1)'[objectNumber]'Objec......
  • SparkStreaming_Dstream创建
    SparkStreaming原生支持一些不同的数据源。一些“核心”数据源已经被打包到SparkStreaming的Maven工件中,而其他的一些则可以通过spark-streaming-kafka等附加工件获......
  • CS1752 无法嵌入互操作类型“XXXXClass“。请改适用的接口
    在打开.Net项目时应用其他库有的提示这个问题,这个原因是由于引入的属性中,有一个“嵌入操作类型”设置 设置为false即可。......