D365以后X++越来越像主流的编程语言了。
D365之前X++类成员变量是不能使用访问修饰符pubic,protected,public的,默认为protected,也就是类及其子类可以访问成员变量。
D365以后可以使用变量修饰符修饰成员变量。
D365之前的类成员变量是不能初始化的,也就是不能在定义的时候赋值,在D365类成员定义的时候可以赋值了。
所以有个有趣的问题,C#和Java初始化成员变量的顺序是不一样的,C#是先初始化类成员变量,再实例化类,所以
在C#里,给类成员变量赋值的时候,不能使用类实例的成员变量或方法。
最简单的一段代码如下所示:
1 public class A 2 { 3 int i ; 4 int j = i; 5 }
上面这段代码是会报编译错误的。
CS0236 字段初始值设定项无法引用非静态字段、方法或属性“A.i”。
说得很明确,不能引用实例字段,因为赋值的时候类还没实例化。
类似的代码在Java是可以正常编译执行的。
1 public class A { 2 int a; 3 int b = a; 4 }
因为Java是先实例化类,然后再给成员变量赋值的。
那么X++是用C#的规则还是Java的规则?
1 class BaseClass 2 { 3 int i = 100; 4 int j = i; 5 }
X++的编译器会报如下错误:
A field initializer cannot reference the non-static field or method 'i'.
显然这跟C#的报错大同小异了,所以规则跟C#是一样的。
X++的编译器还不是很完善,在C#里如果子类的成员变量使用父类的成员变量初始化值,C#在编译的时候,会正确识别,提示同样的报错。
X++遇到这种情况就直接报未将对象引用设置到对象实例,并且也不会告诉你哪一行代码有问题。
Abnormal termination with unhandled exception. Exception key: 2b797ab6-3663-4ed8-8cc1-5076d2a441c9. System.NullReferenceException: 未将对象引用设置到对象的实例。
这种情况应该是因为X++编译器对一些新增的语法特性在编译的时候还不能正确给出提示导致的。
1 class BaseClass 2 { 3 int i = 1; 4 } 5 public class SubClass extends BaseClass 6 { 7 int c = i; 8 }
像这种错误,在C#里是会给出类似如下报错信息,并且会指明出错的地方。
CS0236 字段初始值设定项无法引用非静态字段、方法或属性“A.i”。
在X++里,它就只会报未将对象引用设置到对象的实例。
也不会指出是哪里的问题,会让人怀疑是不是VS的环境出了问题,其实是代码违反了语法导致编译错误,只是X++暂时(10.0.0.10)没办法正确识别。
所以遇到这种非正常终止的错误,可以过一下最近写的代码,考虑一下是不是有语法错误,当然这种场景很少,要不然X++编译器也没法用了。
目前遇到两种情形会出现这个问题,之前提到的属性初始化和这个子类类的成员变量使用父类成员变量赋值的问题。