Archive for the ‘object’ tag
ValueEquals() extension
I have done what I almost never do. I have made an extension method. I don’t like extensions, I believe they increase code complexity and decrease code portability.
Why allow static methods to disguise themselves as instance methods? Well, on the other hand Linq is awesome.
Another move from Hejlsberg & co. that I’m no fan of, is that it is left to the creator of a class to decide if Equals() should mean that two objects are the same (ReferenceEquals()) or simply equal. And when I want the ‘equal’ functionality, I have to implement it.
So I created this:
An extension method that recursively runs through all public fields and properties and check for value equality at node level. It does not support indexed properties, at least not yet and please notice that this uses the MoreLinq extensions.
258 public static bool ValueEquals(this object o, object o2)
259 {
260 Type oType = o.GetType();
261 if (!oType.Equals(o2.GetType())) return false;
262
263 if (o == o2) return true;
264
265 if (o is ValueType || o is string)
266 {
267 return (o.Equals(o2));
268 }
269 else if(o is Array)
270 {
271 return (o as Array).Cast<object>().ZipLongest((o as Array).Cast<object>(), (i1, i2) => i1.ValueEquals(i2)).All(b => b);
272 }
273 else
274 {
275 return oType.GetFields().All(f =>
276 {
277 object v = f.GetValue(o);
278 if (v == null)
279 {
280 return f.GetValue(o2) == null;
281 }
282 else if (v is ValueType || v is string)
283 {
284 return v.Equals(f.GetValue(o2));
285 }
286 else
287 {
288 return v.ValueEquals(f.GetValue(o2));
289 }
290 }) &&
291 oType.GetProperties().All(p =>
292 {
293 object v = null;
294 try
295 {
296 v = p.GetValue(o, null);
297 }
298 catch (TargetParameterCountException)
299 {
300 throw new Exception("Indexed properties are not supported yet");
301 }
302 if (v == null)
303 {
304 return p.GetValue(o2, null) == null;
305 }
306 else if (v is ValueType || v is string)
307 {
308 return v.Equals(p.GetValue(o2, null));
309 }
310 else
311 {
312 return v.ValueEquals(p.GetValue(o2, null));
313 }
314 });
315 }
316 }
Let me know how it works for you..