Slice2CS支持两种不同的枚举映射,默认情况下,如果slice structure只包含value types,那会被映射成C#structure;如果slice structure包含了string、proxy、class、sequence或dictionary成员,则会被映射成C# class。另外我们可以用4.17节介绍的元数据强制一个只包含value type的slice structure映射成c# class.
1 结构映射成结构
有slice结构定义如下:
struct Point {
double x;
double y;
};
这个结构只包含value type,所以会被映射成C# struct:
public struct Point
{
public double x;
public double y;
public Point(double x, double y);
public override int GetHashCode();
public override bool Equals(object other);
public static bool operator ==(Point lhs, Point rhs);
public static bool operator !=(Point lhs, Point rhs);
}
在Slice中定义的每一个数据成员,都被映射成了一个同名的public Field。结构的每一个成员都作为生成的构造函数的一个参数,其顺序和它们在结构中定义的顺序一样。下面的语句允许你构造并初始化一个结构:
Point p = new Point(4.4, 4.3);
上面生成的结构重写了GetHastCode和Equals方法,以允许你将Point做为Key放在dictionary中(注意,有两个参数的staticEquals方法是从System.Object类继承的)。仅当两个结构的每一个数据成员的值相等时,两个结构才是相等;否则,它们就是不相等的。如果结构包含了refrencetype,则Equals操作会进行递归比较,每一次比较都是比较数据成员的值,而不是引用。
2 结构映射成类
结构映射成结构,这是默认情况下的选择,通常这可以满足要求,但是有时,我们会遇到下列的情形:
1 如果我们将结构用做成员的集合,而每一次访问成员都会引起装箱或折箱操作,在这种情况下,性能是很低的。
2 有时,让结构取null值是有意义的。
为了允许你在性能和功能之间取得平衡,Slice2CS编译器提供了将结构映射成类的方法:
["clr:class"] struct Point {
double x;
double y;
};
“clr:class”元指令告诉Slice2CS编译器将Point结构生成为一个类。生成的代码和上面生成的代码类似,不同的地方在于将struct关键字换为了class关键字,并继承自ICloneable接口。
public class Point : System.ICloneable
{
public double x;
public double y;
public Point();
public Point(double x, double y);
public object Clone();
public override int GetHashCode();
public override bool Equals(object other);
public static bool operator ==(Point lhs, Point rhs);
public static bool operator !=(Point lhs, Point rhs);
}
Clone()方法提供了浅copy功能;比较方法执行通常意义上的比较即比较值,而不是比较引用。
注意,你只能在结构定义的起始处决定将结构映射成什么,一旦你决定了,就不能在结构定义的其它地方改变。
正如我们之前所说,如果一个Slice结构包含一个引用类型(refrence types),那即使我们没有添加”clr:calss”元指令,它也会被映射成C# class:
这是一个slice structure定义:
struct Employee {
long number;
string firstName;
string lastName;
};
上面的结构定义有两个string类型的成员,而string类型是refrence type.所以上面的结构用Slice2CS生成的代码如下:
public class Employee : System.ICloneable
{
public long number;
public string firstName;
public string lastName;
public Employee();
public Employee(long number,
string firstName,
string lastName);
public object Clone();
public override int GetHashCode();
public override bool Equals(object other);
public static bool operator ==(Employee lhs, Employee rhs);
public static bool operator !=(Employee lhs, Employee rhs);
}
3 将结构的成员映射成属性
我们可以强制Slice2CS编译器将结构的成员生成为属性,则不是public Field,毕竟这样封装性更好:
["clr:property"]
struct Point {
double x;
double y;
};
上面的定义生成的代码如下:
public struct Point
{
private double x_prop;
public double x
{
get
{
return x_prop;
}
set
{
x_prop = value;
}
}
private double y_prop;
public double y
{
get
{
return y_prop;
}
set
{
y_prop = value;
}
}
// Other methods here...
}
另外,你还可以将多个元指令混合使用:
["clr:property", "clr:class"]
struct Point {
double x;
double y;
};
上面的定义生成的代码如下:
using System;
public class Point : ICloneable
{
private double x_prop;
private double y_prop;
public virtual double x
{
get
{
return x_prop;
}
set
{
x_prop = value;
}
}
public virtual double y
{
get
{
return y_prop;
}
set
{
y_prop = value;
}
}
// Other methods here...
}