Csharp高级面向对象

Csharp高级面向对象

Object类型

对于C# 中所有Class,默认的最终基类都是Object类(System命名空间下,简写为object)

同Java一样,C#的Object同样提供了一些方法


ToString方法

用于“打印”当前对象信息,即将当前对象的字段们都转化为字符串,以一定格式打印输出

默认情况打印当前对象的全类名

我们需要在类中重写此方法,以完成对对象中内容的输出


GetType方法

此方法会返回一个Type类型的对象(System命名空间提供的类型),这个对象提供了一些方法

这些方法可以获取对象的运行时类信息,常常用于反射

  • FullName方法:获取当前对象的类全名
  • Name方法:获取当前对象的类名
  • IsValueType方法:判断当前对象是否为值类型
  • IsClass方法:判断当前对象是否为引用类型

Equals方法

判断两个对象是否相等

==用于判断值类型的值相同、引用类型的地址相同、字符串的字符相同

Equals方法如果不被重写,那么他的运行逻辑和==是一样的

我们需要在类中重写此方法,以完成对对象中内容的相等判断

class User
{
    public string? Name { get; set; }
    public int Age { get; set; }

    public override bool Equals(object? obj)
    {
        // 使用as关键字判断传入的对象是否为User对象
        var user = obj as User;
        // 如果不为User对象,则返回不相等
        if (user == null)
        {
            return false;
        }
        
        // 判断传入对象的属性是否相等
        return user.Name == Name && user.Age == Age;
    }
}

AS&IS关键字

在C#中,as 关键字用于尝试将一个对象转换为其基类或接口类型,这是一种安全的向下转型(downcast)的方式。如果转换成功,as 将返回转换后的对象;如果失败,则返回 null(对于引用类型)或默认值(对于值类型)。这种方法不会抛出异常,因此是一种较为安全的类型转换方式。

is 关键字用于测试一个对象是否是某个类型的实例,或者是否可以转换为某个接口类型

as 关键字提供了一种安全的方式来执行类型转换,特别适用于需要向下转型的场景。与 is 结合使用时,可以进一步提高代码的安全性和可读性。使用 as 进行转换不会抛出异常,而是返回 null 或默认值,这使得它成为处理不确定类型的对象时的一个好选择


泛型

C#的泛型与Java并没有显著区别,所以具体可以参考笔记中的Java中的泛型知识点

当使用泛型方法在方法内部做数据处理时,我们会遇到意料之外的报错

public static T Add<T>(T a, T b)
{
    return a + b;// 这样写会报错
}

通过dynamic关键字来将类型校验推迟到运行时,而不是在编译时进行类型校验

dynamic中文释义:动态

public static T Add<T>(T a, T b)
{
    dynamic? da = a;
    dynamic? db = b;
    // 这时,当传入的参数类型违法时,会在运行时报错,而不是编译时报错
    return da + db;
}

泛型类可以被继承,在继承时,可以选择对泛型的特化与不特化(子类同时继承泛型类状态),同时,子类可以在父类的基础上添加更多个泛型类型


泛型约束

接口约束

使用where关键字对泛型类型加以约束,使用接口的形式规定这个泛型类型必须包含某些可以执行的方法

接口约束可以同时存在多个,以逗号分隔

public interface IHello
{
    public void SayHello();
}

// 对泛型类型加以约束,确保该类型的对象中存在此方法
public class HelloWorld<T> where T : IHello
{
    public void Hello(T t)
    {
        t.SayHello();
    }
}

class约束

使用where关键字配合class关键字来约束泛型的类型必须为引用类型

在C#中,class的关键字的含义即为引用类型

public class HelloWorld<T> where T : class
{
    
}

struct约束

使用where关键字配合struct关键字来约束泛型的类型必须为值类型

注:在C#中,结构体类型为值类型数据

public class HelloWorld<T> where T : struct
{
    
}

new()约束

使用where关键字配合new()关键字来约束泛型类型中必须存在无参构造方法

既然必须存在无参构造方法,那么该类型也一定是引用类型(class)

如果存在多个泛型约束,那么new()约束必须放到最后才能成立

public class HelloWorld<T> where T : new()
{
    
}

类名约束

使用where关键字配合类名来约束泛型类型中必须为该类或该类的子类

可以与接口约束同时存在,但是必须写在最前面且唯一(有点像类的继承)

class HelloWorld<T> where T : User
{
    
}

多泛型约束

使用where关键字对多个占位符进行分别的约束

class HelloWorld<T,R> where T : struct where R : class
{
    
}