初解C#类、结构、弱引用
一、类
类中的数据和函数称为类的成员
数据成员是包含类的数据----字段、常量和事件的成员。数据成员可以是静态数据、类成员总是实例成员,除非用static进行显示的声明。
事件是类的成员,在发生某些行为(如改变类的字段或属性,或者进行了某种形式的用户交互操作)时,他可以让对象通知调用方,调用方可以包含所谓“事件处理程序”的代码来响应该事件。
函数成员提供了操作类中数据的某些功能,包括方法、属性、构造函数和终结器(finalizer)、运算符以及索引器。
(1)方法是与某个类相关的函数,与数据成员一样,函数成员默认为实例,使用static修饰符可以把方法定义为静态方法
(2)属性是可以从客户段访问的函数组,其访问方式与访问类的公共字段类似。C#为读写类中的属性提供了专用语法,所以不必使用那些名称中嵌有Get或Set的方法。因为属性的这种语法不同于一般函数的语法,在客户端代码中,虚拟的对象被当作实际的东西
(3)构造函数是在实例化对象时自动调用的特殊函数,它们必须与所属的类同名,且不能有返回类型。构造函数用于初始化字段的值
(4)终结器类似构造函数,但是在CLR检测到不再需要某个对象时调用它,它们的名称与类相同,但前面有一个“~”符号,不可能预测什么时候调用终结器
(5)运算符执行最简单的操作就是加法和减法,C#还允许运算符重载
如下是一个包含静态构造函数和索引的类的定义和测试
class Program { static void Main(string[] args) { Console.WriteLine(UserPreferences.BackColor); var testUserPreference = new UserPreferences(101); Console.WriteLine(UserPreferences.BackColor); try { Console.WriteLine(testUserPreference["Sun"]); } catch (ArgumentOutOfRangeException e) { Console.WriteLine(e.Message); } Console.ReadKey(); } } public class UserPreferences { //用于测试当提供类的静态构造函数之后类的静态字段不会随实力初始化而改变,当然也可以直接给变量赋初始值 public static string BackColor; public static int Version; public int Age { get; set; } public string Name { get; set; } static UserPreferences() { var dtTime = DateTime.Now; if (dtTime.DayOfWeek.Equals(DayOfWeek.Saturday) || dtTime.DayOfWeek.Equals(DayOfWeek.Sunday)) BackColor = "Green"; else BackColor = "Red"; } string[] days = { "Sun", "Mon", "Tues", "Web", "Thurs", "Fri", "Sat" }; //串联构造函数 public UserPreferences() { } public UserPreferences(int age) : this(age, "") { } public UserPreferences(string name) : this(0, name) { } public UserPreferences(int age, string name) { if (age > 100) Age = 0; else Age = age; Name = name; } public int this[string day] { get { return GetDay(day); } } /// <summary> /// 定义索引器获取数据的方法 /// </summary> /// <param name="testDay"></param> /// <returns></returns> private int GetDay(string testDay) { for (int j = 0; j < days.Length; j++) { if (days[j] == testDay) { return j; } } throw new ArgumentOutOfRangeException(testDay, "testDay must be in the form \"Sun\", \"Mon\", etc"); } }
从中可以得出静态构造函数的特性:一个类(结构)只能定义一个静态构造函数,静态构造函数不允许访问修饰符并且不能接受任何参数,无论创建多少个类实例,静态函数知执行一次、CLR创建类实例或首次调用类静态成员前,CLR会调用静态构造函数、静态构造函数先于实例级别的其他构造函数执行。参考https://msdn.microsoft.com/en-us/library/2549tw02.aspx
二,结构
结构是值类型,不是引用类型。它们存储在栈中或存储未内联,其生存期的限制和简单的数据类型一样,对于结构:不支持继承,编译器总是提供一个无参的默认构造函数,并且不允许替换,使用结构可以指定字段如何在内存中布局,默认的构造函数把数值初始化为0,把引用类型初始化为null,且总是隐式指出的,如下定义的结构:
struct Dimensions { public double Length; public double Width; public Dimensions(double length, double width):this() { Length = length; Width = width; } }
三、弱引用
弱引用允许创建和使用对象,但是GC运行时就会回收对象并释放内存,当object比较大时运用弱引用是合理的,如下:
WeakReference userReference = new WeakReference(new UserPreferences(3, "yoyo")); UserPreferences userModel; if (userReference.IsAlive) { userModel = userReference.Target as UserPreferences; Console.WriteLine(userModel.Age); }
在弱引用创建时,会向其构造函数传递一个新的引用对象,在要重新访问对象是必须通过IsAlive属性来判断对象是否被GC回收,如果被回收的话要重新创建。