c# - How to check whether generic objects are equal that works for strings -


i ran wierd behaviour today whilst refactoring code.

i had code looked this:

    private atype blah     {                 {             return (from in alist                     _x == null || something.x == _x                     _y == null || something.y == _y                     _z == null || something.z.issameas(_z)                     select something).single();         }     } 

i've anonomised type , variable names aren't important question.

the type of _x , something.x string , _y , something.y reference type. likewise _z , something.z reference type value comparison.

i thought this:

    public atype blah     {         { return alist.single(something => detailsmatch(something.x, something.y, something.z)); }     }      private bool detailsmatch(string x, anothertype y, afurthertype z)     {         return nullorcheck(_x, x) &&                nullorcheck(_y, y) &&                nullorcheck(_z, z.issameas);     }      private bool nullorcheck<t>(t value, t expected) t : class     {         return nullorcheck(value, v => v == expected);     }      private static bool nullorcheck<t>(t value, func<t,bool> check) t : class     {         return value == null || check(value);     } 

this seemed make sense surprise tests started failing. turned out identical strings (the example "1a04" , "1a04") no longer being considered equal using == operator.

having looked @ following can't operator == applied generic types in c#? seems strings being compared on reference equality instead of in normal manner.

is there safe way in c# or should using == in generic method considered dangerous above reason?

just confirm problem fix consisted of inlining offending methods in string case resulting in:

    private bool detailsmatch(string x, anothertype y, afurthertype z)     {         return (_x == null || _x == x) &&                nullorcheck(_y, y) &&                nullorcheck(_z, z.issameas);     } 

hey presto - works , tests pass again

you can use object.equals:

return nullorcheck(value, v => object.equals(v, expected)); 

the string class overloads static == operator compare 2 string arguments equality i.e.

string first = "abc"; string second = "abc";  bool eq = first == second; 

the call == use overloaded == strings, since static type of first , second both string.

however, in

object first = "abc"; object second = "abc"; bool eq = first == second; 

the == operator used 1 defined object since static type of first , second object. note in case, due string interning, first , second contain reference same string, not case in general.

in generic method, == resolve static == defined object instead of more specific version defined string. since == simple reference equality check objects, behaves differently.

the equals method virtual , can overridden specialise equality checks custom types. therefore in

object first = "abc"; object second = "abc"; bool eq = first.equals(second); 

the string.equals method called, check strings have same values, instead of same reference.

the static object.equals method uses virtual equals instance method, check strings have same value instead of pointing same string instance. static object.equals checks argument null, safer calling obja.equals(objb) directly.


Comments

Popular posts from this blog

jquery - How can I dynamically add a browser tab? -

node.js - Getting the socket id,user id pair of a logged in user(s) -

keyboard - C++ GetAsyncKeyState alternative -