.NET的基础类Object
有一个Equals
方法,这个方法用来比较两个对象是否相等,默认的实现是比较两个引用是否相同,相当于==
操作符。对于不同的子类可能会有不同的实现,本篇就来研究一下delegate的equals方法。
首先是msdn上给出的说明
按照以下方式比较这些方法和目标是否相等:
- 如果所比较的两种方法都是静态的且对同一类为同一方法,则这些方法被视为相等,这些目标也被视为相等
- 如果所比较的两种方法都是实例方法且对同一个对象为同一种方法,则这些方法被视为相等,这些目标也被视为相等。
- 否则,这些方法被视为不相等,这些目标也被视为不相等。 仅当两个调用列表具有相同顺序,并且两个列表的对应元素表示相同的方法和目标时,这两个调用列表才会被视为相同。
利用以上规则通常可以判断大部分情况的比较结果,但是如果用到了匿名方法,比如lambda表达式
的时候应该怎么处理呢。带着这个问题我做了个小实验。
首先定义了一个类生产不同的delegate对象,一个用到了成员变量_value,一个用到了静态变量_svalue,一个没有用到任何变量:
class ClosureEnv { private static int _svalue = 4; private int _value;
public ClosureEnv(int n) { _value = n; }
public Func<int> CreateMethod() { return () => 2; }
public Func<int> CreateMethodUseMember() { return () => _value; }
public Func<int> CreateMethodUseStaticMember() { return () => _svalue; } } |
然后定义两个对象分别生产delegate,然后比较它们是否相同:
static void Main(string[] args) { ClosureEnv env1 = new ClosureEnv(2); ClosureEnv env2 = new ClosureEnv(2);
Console.Write("Unuse member: "); if (env1.CreateMethod().Equals(env2.CreateMethod())) { Console.WriteLine("Equals"); } else { Console.WriteLine("Unquals"); }
Console.Write("Use member: "); if (env1.CreateMethodUseMember().Equals(env2.CreateMethodUseMember())) { Console.WriteLine("Equals"); } else { Console.WriteLine("Unquals"); }
Console.Write("Use member with same object: "); if (env1.CreateMethodUseMember().Equals(env1.CreateMethodUseMember())) { Console.WriteLine("Equals"); } else { Console.WriteLine("Unquals"); }
Console.Write("Use static member: "); if (env1.CreateMethodUseStaticMember().Equals(env2.CreateMethodUseStaticMember())) { Console.WriteLine("Equals"); } else { Console.WriteLine("Unquals"); }
Console.ReadKey(); } |
运行结果如下:
通过结果可以发现:
- 当用到外部类成员变量的时候,生成的匿名方法其实属于外部类的实例方法
- 否则生成的匿名方法属于外部类的静态方法