小心委托
小心委托
在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 阅读(1779) 评论(16) 编辑 收藏 举报