小心委托

 

小心委托

C#语言规范中,对委托(delegate)的描述有这么一句话:“委托同时封装了对象实例和方法”,我用一段小程序来说明这句话的含义,以解答各位在使用委托时出现的奇怪现象。

首先定义一个delegate,一个不带参数,只返回字符串的简单委托类型:

public delegate string ReturnStringFunc();

下面的类使用了这个委托,请大家留意委托的使用方法:

public class DelegateTest

{

    public DelegateTest()

    {

        func = GetA;

    }

    private static ReturnStringFunc func;

    public ReturnStringFunc Func

    {

        get

        {

            return func;

        }

    }

    private string a;

    public string A

    {

        get { return a; }

        set { a = value; }

    }

    public string GetA()

    {

        return a;

    }

    static void Main()

    {

        DelegateTest a = new DelegateTest();

        a.A = "A";

        Console.WriteLine(a.Func());

        DelegateTest b = new DelegateTest();

        b.A = "B";

        Console.WriteLine(b.Func());

        Console.WriteLine(a.Func());

        Console.ReadLine();

    }

}

这个类中,定义了一个内部静态变量func,然后通过成员属性Func将其公开。另外写了个成员方法GetA(),并在构造函数中把成员方法GetA()赋给静态变量func。成员方法GetA()直接返回类成员变量a

Main()函数中测试调用Func()方法情况。输出结果如下:

A

B

B

即,第一个a.Func()返回的是DelegateTest的实例a.a的值。在b.Func()中,结果也正如大家所料,是b.a的值。这时,我们再次调用a.Func()时,其值往往会以为是a.a的值,实际结果却是b.a的值。为什么如此?

我是在类实例构造中给静态代理赋值的。这时,大家回想刚才那句话“委托同时封装了对象实例和方法”,对结果就会容易理解些了。在静态代理中,不仅仅保存了类的方法,同时还保存了对象的实例。即第一次构造a的时候静态代理保存的是实例a,在构造b的时候静态代理保存的是实例b。因此就出现了调用a.Func()却得到b.a的值了!

这个问题的避免是:在使用静态代理的时候,要小心把成员方法赋给它。

posted on 2007-09-19 22:34  sdxd.bgl  阅读(1777)  评论(16编辑  收藏  举报

导航