看看什么是 static class 吧,很久以前我就为不能声明一个 abstract sealed class
而苦恼不已,我在 CSDN 上曾经提出过这个问题,可是并没有获得共鸣。我得到的回复
是这样的:
abstract 和 sealed一起用?定义abstract的目的就是抽象基类,seal表示不能继承的
实体类,完全是两回事,怎么可能一起用呢?
abstract表明必须要被继承,sealed表明不可以被继承,这两个是矛盾的,怎么可以一
起用呢。
通过查看 IL 代码,我们会发现 static class 实际上就是 abstract sealed class,
只不过编译器在编译时顺便对 static class 的成员修饰符进行检查而已。
让我们再来猜测一下 MS 开发人员的想法:他们的目的是想获得 abstract sealed
class 的效果,但却为语义上的矛盾而苦恼不已,大家想获得一个优美的解决方式,于
是就为 C 2.0 新增了一个 static 关键字,完美的解决了这个问题。
也许有人会问:为什么不是 static class = abstract class + static member limit
而要加上 sealed 的限制呢?理由是继承一个只有 static 成员的类和重新写一个类完
全没有区别。为什么这么说呢?因为 static 必然是not virtual,继承它又能有什么
用呢?
static class 还有一个限制,那就是只能从 System.Object 继承,为什么会有这个限
制,理由和上面差不多。
每每提到 static 关键字,我就想起了 static constructor,感谢 MS 的开发人员提
供了这么好的一个特性。但是 C 提供了 static constructor 却没有提供 static
destructor,不过在 Applied Microsoft .NET Framework Programming 一书中
Jeffery Richter 给我们提供了一个办法就是通过 System.AppDomain.DomainUnload
事件去达到同样的效果。
使用 static constructor 要注意的就是这里抛出任何异常都会导致该类型在重新加载
AppDoamin 之前不再可用,所以要加倍小心,另外 static contructor 中很容易有两
个类型死锁的情况发生,在编写代码的时候一定要想清楚。
而苦恼不已,我在 CSDN 上曾经提出过这个问题,可是并没有获得共鸣。我得到的回复
是这样的:
abstract 和 sealed一起用?定义abstract的目的就是抽象基类,seal表示不能继承的
实体类,完全是两回事,怎么可能一起用呢?
abstract表明必须要被继承,sealed表明不可以被继承,这两个是矛盾的,怎么可以一
起用呢。
通过查看 IL 代码,我们会发现 static class 实际上就是 abstract sealed class,
只不过编译器在编译时顺便对 static class 的成员修饰符进行检查而已。
让我们再来猜测一下 MS 开发人员的想法:他们的目的是想获得 abstract sealed
class 的效果,但却为语义上的矛盾而苦恼不已,大家想获得一个优美的解决方式,于
是就为 C 2.0 新增了一个 static 关键字,完美的解决了这个问题。
也许有人会问:为什么不是 static class = abstract class + static member limit
而要加上 sealed 的限制呢?理由是继承一个只有 static 成员的类和重新写一个类完
全没有区别。为什么这么说呢?因为 static 必然是not virtual,继承它又能有什么
用呢?
static class 还有一个限制,那就是只能从 System.Object 继承,为什么会有这个限
制,理由和上面差不多。
每每提到 static 关键字,我就想起了 static constructor,感谢 MS 的开发人员提
供了这么好的一个特性。但是 C 提供了 static constructor 却没有提供 static
destructor,不过在 Applied Microsoft .NET Framework Programming 一书中
Jeffery Richter 给我们提供了一个办法就是通过 System.AppDomain.DomainUnload
事件去达到同样的效果。
使用 static constructor 要注意的就是这里抛出任何异常都会导致该类型在重新加载
AppDoamin 之前不再可用,所以要加倍小心,另外 static contructor 中很容易有两
个类型死锁的情况发生,在编写代码的时候一定要想清楚。
我为什么要使用static class:
其实,static class 给了我们 abstract sealed class 同样的效果,而我为什么想要得到 abstract sealed 的效果呢,以下是我之前产生这个想法的原因,至于 ms 引入 static class 真正的原因,我就不知道了。
假设我要写一个简单的func,用来处理字符串,它的功能就是给传入的字符串加上单引号并将已有的单引号替换掉:
public String Quote(String Str)
{
return "'" + Str.Replace("'","''" + "'";
}
这个函数很简单,可是在 C# 中,我把它放在什么地方呢?它必须是某个类的一员:
public class Utility
{
public String Quote(String Str){}
}
1、我不希望它每次处理字符串的时候还要创建一个 Utility 对象实例,所以 Quote 函数必须是 static 的。
2、既然 Utility 类只提供这样类似的 static 方法,所以它没有必要被实例化。
3、我不希望有人继承 Utility 类,这是一件无意义的事情,因为它的成员都是 static 的。
我希望能写这样的代码:
public abstract sealed class Utility
{
public static String Quote(String Str){}
}
可是它并不能通过编译,C# 2.0中仍然不能,但是我可以用 static 来代替 abstract sealed 。
也许你会说这样也可以:
public sealed class Utility
{
private Utility(){}
public static String Quote(String Str){}
}
这样确实也可以,也许我的理由很牵强,但是我总觉得,这个不是那么优美,感觉是用了一个技巧。
用 static class 在 语义 上显得更加优美。
至少,一看就能明白,不用在尝试实例化 Utility 失败以后去寻找出错的原因。
或许很牵强,我总是会有这种不切实际的苛求。但 ms 还是满足了我的苛求。
------------------------------
其实,static class 给了我们 abstract sealed class 同样的效果,而我为什么想要得到 abstract sealed 的效果呢,以下是我之前产生这个想法的原因,至于 ms 引入 static class 真正的原因,我就不知道了。
假设我要写一个简单的func,用来处理字符串,它的功能就是给传入的字符串加上单引号并将已有的单引号替换掉:
public String Quote(String Str)
{
return "'" + Str.Replace("'","''" + "'";
}
这个函数很简单,可是在 C# 中,我把它放在什么地方呢?它必须是某个类的一员:
public class Utility
{
public String Quote(String Str){}
}
1、我不希望它每次处理字符串的时候还要创建一个 Utility 对象实例,所以 Quote 函数必须是 static 的。
2、既然 Utility 类只提供这样类似的 static 方法,所以它没有必要被实例化。
3、我不希望有人继承 Utility 类,这是一件无意义的事情,因为它的成员都是 static 的。
我希望能写这样的代码:
public abstract sealed class Utility
{
public static String Quote(String Str){}
}
可是它并不能通过编译,C# 2.0中仍然不能,但是我可以用 static 来代替 abstract sealed 。
也许你会说这样也可以:
public sealed class Utility
{
private Utility(){}
public static String Quote(String Str){}
}
这样确实也可以,也许我的理由很牵强,但是我总觉得,这个不是那么优美,感觉是用了一个技巧。
用 static class 在 语义 上显得更加优美。
至少,一看就能明白,不用在尝试实例化 Utility 失败以后去寻找出错的原因。
或许很牵强,我总是会有这种不切实际的苛求。但 ms 还是满足了我的苛求。
------------------------------
反编译一下,会了解其实现机制。
原来编译器将该类声明为 abstract sealed,自然不能被继承被实例化了。
但是C#编译器并不允许我们在代码中直接声明一个abstract sealed类型,下面的代码无法通过编译。
静态类的限制
1. 静态类不能有实例构造器。
2. 静态类不能有任何实例成员。
3. 静态类上不能使用abstract和sealed修饰符。
4. 静态类默认继承自System.Object,不能显式指定任何其他基类。
5. 静态类不能指定任何接口实现。
6. 静态类的成员不能有protected或者protected internal访问保护修饰符。
但是C#编译器并不允许我们在代码中直接声明一个abstract sealed类型,下面的代码无法通过编译。
静态类的限制
1. 静态类不能有实例构造器。
2. 静态类不能有任何实例成员。
3. 静态类上不能使用abstract和sealed修饰符。
4. 静态类默认继承自System.Object,不能显式指定任何其他基类。
5. 静态类不能指定任何接口实现。
6. 静态类的成员不能有protected或者protected internal访问保护修饰符。