IMZRH的日志

努力成为一个有用的人

导航

ICE框架之Sclice2CSharp映射---结构的映射

Posted on 2008-05-13 17:40  张荣华  阅读(988)  评论(0编辑  收藏  举报

Slice2CS支持两种不同的枚举映射,默认情况下,如果slice structure只包含value types,那会被映射成Cstructure;如果slice structure包含了stringproxyclasssequencedictionary成员,则会被映射成C# class。另外我们可以用4.17节介绍的元数据强制一个只包含value typeslice 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);

上面生成的结构重写了GetHastCodeEquals方法,以允许你将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...

}