1,不彻底的abstract
即使是abstract class,也不能对实现的接口的某个成员视而不见,即下面这样是不允许的:
interface in_one{
void A();
}
abstract class base_one : in_one{
}
这一点上还是Java方便,不管C#的初衷是什么
2,out参数与指针的指针
out子类不能转化为out基类,如果允许转换的化,将无法保证类型安全性;即out参数相当于指针的指针,而父类的指针与子类的指针是没有继承关系的,所以不能转化
3,强制针对接口编程
针对接口编程只是一个一般性的原则,但C#提供了一种机制,强迫客户程序员根据接口来引用你的实现类:显式接口成员
interface A{
void a();
}
class A_Sub:A {
void A.a() {
}
}
static void Main(string[] args)
{
((A)new A_Sub()).a(); //OK!
new A_Sub().a(); //Error!
}
显式接口成员实现程序跟其他成员相比,有不同的访问能力特性。因为显式接口成员不能通过实现类访问,所以,它们从感觉上是私有的。但是,由于它们可以通过接口引用访问,从感觉上它们又是公共的。
显式接口成员实现程序主要服务于两个目的:
a,类或结构实现一个客户不感兴趣的内部接口
b,用相同的签名消除接口成员的歧义
为了使显式接口成员实现程序有效,类或成员必须在它的基本类列表中命名一个接口,这个列表中包含一个成员,它的全部有效名称、类型和参数类型与显式接口成员实现程序的那些要完全一致
4,@ 取消转义
取消字符串转义尚可理解,不过连关键字都变成普通标识了,实在看不出有多大意义
5,struct的构造函数
自定义的ctor并不能隐藏默认的无参构造函数,稍有意外,却也在情理之中,默认无参构造函数对于struct有良好定义的语义
6,const,readonly
const相当于C++的static const
readonly相当于C++的const
所以,const相当于static readonly,当然,还是有些区别,const编译时获得值,static readonly运行时
public class Color {
public const Color Black = new Color(0, 0, 0); //error
public static readonly Color White = new Color(255, 255, 255); //ok
private Color(byte r, byte g, byte b) {
}
}
7,自然的boxing,unboxing
string s = "abc";
object o = s;
int i = 123;
object o = i;
对于string的例子都不会吃惊,为什么要特殊对待int的例子呢?string是System.String的别名,只要把int当作System.Int32的别名,一切不都很自然了吗?int确实是System.Int32的别名,int和string还是有区别的,boxing后的值会被复制,数组调用很明确的不会扩展到数值类型的数组
或许是效率的原因吧
8,智能的自定义转型
C++不允许一次转换中调用超过一次的自定义转型操作符,C#同样不允许,不同的是C#会在调用自定义转型操作符前后为源类型和目标类型各插入一次自动寻找的标准转型操作,如果需要的话;简单的说;
9,操作符重载
C++里内存由程序员管理,允许重载new操作符,C#则理所当然的禁止了对new的重载
C++里算术运算符+-*/等重载后,其结合形式+=,-=,*=,/=不会被自动重载,C#为了保证语义一致性,自动重载了它们的结合形式
C++里短路逻辑运算符&&,
关键词:The C# Programming Language Notes