C# sealed 、GetType、序列化static
一、GetType()
获取对象的运行时类型(返回 Type
)
public static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
int num = 10;
string text = "abcd";
double pi = 3.1415925;
Console.WriteLine(num.GetType()); // 输出:System.Int32
Console.WriteLine(text.GetType()); // 输出:System.String
Console.WriteLine(pi.GetType()); // 输出:System.Double
Console.ReadLine();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// Application.Run(new Form1());
}
typeof()
vs. GetType()
int num = 10;
string text = "abcd";
double pi = 3.1415925;
//Console.WriteLine(num.GetType()); // 输出:System.Int32
//Console.WriteLine(text.GetType()); // 输出:System.String
//Console.WriteLine(pi.GetType()); // 输出:System.Double
Type type1 = typeof(int) ; // 编译的时候确定
Type type2= num.GetType(); // 运行的时候确定
Console.WriteLine(type1 == type2); // 输出:True
结论:
typeof(T)
用于在编译时获取类型,不需要实例。obj.GetType()
用于在运行时获取对象的真实类型,需要实例。
GetType()
与 继承
如果类有继承,GetType()
返回实际子类的类型。
class Parent { }
class Child: Parent { }
public static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Parent obj=new Child();
Console.WriteLine(obj.GetType()); // 输出:Child
Console.ReadLine();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// Application.Run(new Form1());
}
说明:
obj
的编译时类型是Parent
,但GetType()
返回Child
,因为obj
实际是Child
类型的实例。
GetType()
获取类的详细信息
可以使用 GetType()
获取类的详细信息,如属性、方法等:
class Sample
{
public int Number { get; set; }
public void SayHello() => Console.WriteLine("Hello");
}
public static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Sample obj = new Sample();
Type type = obj.GetType(); // Sample
Console.WriteLine($"类名: {type.Name}");
Console.WriteLine($"命名空间: {type.Namespace}");
Console.WriteLine("属性列表:");
foreach (var prop in type.GetProperties())
{
Console.WriteLine($"- {prop.Name} ({prop.PropertyType})");
}
//- Number (System.Int32)
Console.WriteLine("方法列表:");
foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance))
{
Console.WriteLine($"- {method.Name}");
}
// SayHello
//Parent obj=new Child();
//Console.WriteLine(obj.GetType()); // 输出:Child
Console.ReadLine();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// Application.Run(new Form1());
}
总结
GetType()
获取字段方法
class Sample
{
public int PublicField = 42;
private string PrivateField = "Secret";
public static int StaticField = 99; // 静态字段(不会被获取)
public static string StaticField2 = "hello"; // 静态字段(不会被获取)
}
public static class Program
{
[STAThread]
static void Main()
{
Sample obj = new Sample();
Type type = obj.GetType();
#region 属性字段
FieldInfo[] fields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
Console.WriteLine("实例字段列表:");
foreach (var field in fields)
{
Console.WriteLine($"- {field.Name} (类型: {field.FieldType}, 值: {field.GetValue(obj)})");
}
#endregion
Console.WriteLine("---------------------------------------------------------------");
#region 获取静态字段
FieldInfo[] staticFields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
foreach (var field in staticFields)
{
Console.WriteLine($"- {field.Name} (类型: {field.FieldType}, 值: {field.GetValue(obj)})");
}
#endregion
Console.ReadLine();
}
二、sealed class
在 C# 中,sealed class
是密封类,它的作用是防止该类被继承。
sealed
关键字的作用
- 防止类被继承(
sealed class
)。 - 防止方法被子类重写(
sealed override
)。 -
sealed class sealedClassTest { public void ShowMessage() { Console.WriteLine("This is a sealed class."); } } class SubClass : sealedClassTest { } // 报错:'sealedClassTest' 不能被继承
sealed override
(防止方法被重写)
class BaseClass
{
public virtual void VirtualMethod()
{
Console.WriteLine("BaseClass Method");
}
}
class DerivedClass : BaseClass
{
/// <summary>
/// sealed 这个方法加了sealed 来修饰,就不能被重写
/// </summary>
public sealed override void VirtualMethod()
{
Console.WriteLine("DerivedClass Method");
}
}
class SubDerivedClass : DerivedClass
{
public override void VirtualMethod() { } // 报错:不能重写被 sealed 关键字修饰的方法
}
sealed class
的应用场景
✅ 何时使用 sealed
?
- 安全性:防止类被继承,确保核心逻辑不会被篡改。
- 优化性能:密封类比可继承类的调用更快(编译器可进行优化)。
- 特定用途的类:如
System.String
、System.Math
这些类本身就是sealed
,不允许继承
序列化 sealed 类
sealed 类 ISerializable
自定义序列化
[Serializable]
sealed class Person : ISerializable
{
public string Name { get; set; }
public int Age { get; set; }
public Person() { }
// 序列化构造函数(反序列化时调用)
private Person(SerializationInfo info, StreamingContext context)
{
Name = info.GetString("Name");
Age = info.GetInt32("Age");
}
// 自定义序列化逻辑
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Name", Name);
info.AddValue("Age", Age);
}
}
public static class Program
{
static void Main()
{
Person person = new Person { Name = "Alice", Age = 30 };
// 二进制序列化
IFormatter formatter = new BinaryFormatter();
using (Stream stream = new FileStream("person.bin", FileMode.Create, FileAccess.Write))
{
formatter.Serialize(stream, person);
}
Console.WriteLine("对象已序列化!");
Console.ReadLine();
}
}
三、序列化static
在 C# 中,static
变量默认不能被序列化,因为它属于类本身,而不是对象的实例。
但如果你确实需要序列化 static
变量,可以使用以下几种方法:
手动序列化 static
变量(不推荐)
[Serializable]
class Hero
{
public string Name { get; set; }
public int Age { get; set; }
public static string staticVar = "this is a string var";
public Hero() { }
// 序列化的时候使用
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Name", Name);
info.AddValue("Age", Age);
// 手动存储静态变量
info.AddValue("staticVar", staticVar);
}
// 反序列化时调用
private Hero(SerializationInfo info, StreamingContext context)
{
Name = info.GetString("Name");
Age = info.GetInt32("Age");
// 手动恢复静态变量(⚠️ 仅适用于全局单例的场景)
staticVar = info.GetString("staticVar");
}
}
public static class Program
{
static void Main()
{
// 设置静态变量
Hero.staticVar = "staticvar in main";
Hero hero = new Hero();
hero.Name = "Albert";
hero.Age = 27;
// 开始序列化
IFormatter formatter = new BinaryFormatter(); // 二进制序列化
using (Stream stream=new FileStream("hero.bin",FileMode.Create,FileAccess.Write))
{
formatter.Serialize(stream,hero);
}
// 修改静态变量,验证反序列化是否恢复
Hero.staticVar = "abcedfghig";
// 开始反序列化
using (Stream stream = new FileStream("hero.bin", FileMode.Open, FileAccess.Read))
{
hero = (Hero)formatter.Deserialize(stream);
}
Console.WriteLine($"StaticData after deserialization: {Hero.staticVar}"); // "Static Data Before Serialization"
Console.ReadLine();
}
}
使用 JsonSerializer
手动处理 static
变量(推荐)
class Person
{
public string Name { get; set; }
public int Age { get; set; }
public static string StaticData = "This is static";
// 手动添加静态变量
public string StaticDataSerialized => StaticData;
}
public static class Program
{
static void Main()
{
Person person = new Person { Name = "Alice", Age = 30 };
// 🔹 序列化
string json = JsonSerializer.Serialize(person);
Console.WriteLine(json);
Console.ReadLine();
}
}
序列化 static
变量到单独的文件(强烈推荐)
static class GlobalConfig
{
public static string Setting = "Dark Mode";
public static void SaveConfig()
{
File.WriteAllText("config.json", JsonSerializer.Serialize(Setting));
}
public static void LoadConfig()
{
if (File.Exists("config.json"))
{
Setting = JsonSerializer.Deserialize<string>(File.ReadAllText("config.json"));
}
}
}
// 保存
GlobalConfig.SaveConfig();
// 修改静态变量
GlobalConfig.Setting = "Light Mode";
// 重新加载(恢复之前的值)
GlobalConfig.LoadConfig();
Console.WriteLine(GlobalConfig.Setting); // 输出:"Dark Mode