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
{
}