c# - Using a class versus struct as a dictionary key -
suppose had following class , structure definition, , used them each key in dictionary object:
public class myclass { } public struct mystruct { } public dictionary<myclass, string> classdictionary; public dictionary<mystruct, string> structdictionary; classdictionary = new dictionary<myclass, string>(); structdictionary = new dictionary<mystruct, string>();
why works:
myclass classa = new myclass(); myclass classb = new myclass(); this.classdictionary.add(classa, "test"); this.classdictionary.add(classb, "test");
but crashes on runtime:
mystruct structa = new mystruct(); mystruct structb = new mystruct(); this.structdictionary.add(structa, "test"); this.structdictionary.add(structb, "test");
it says key exists, expected, struct. class treats 2 separate entries. think has data being held reference versus value, more detailed explanation why.
new object() == new object()
false, because reference types have reference equality , 2 instances not same referencenew int() == new int()
true, because value types have value equality , value of 2 default integers same value. note, if have reference types or default values incremental in struct, defaults may not compare equal structs either.
you can override equals
, gethashcode
methods , equality operators of both structs , classes if don't default equality behavior.
also, if want safe way set dictionary value, regardless, can dictionary[key] = value;
add new values or update old ones same key.
update
@280z28 posted a comment pointed out how answer misleading, recognize , want address. it's important know that:
by default, reference types'
equals(object obj)
method ,==
operator callobject.referenceequals(this, obj)
under hood.the operators , instance methods need overridden propagate behavior. (e.g. changing
equals
implementation not affect==
implementation, unless nested call added explicitly).all default .net generic collections use
iequalitycomparer<t>
implementation determine equality (not instance method).iequalitycomparer<t>
may (and does) call instance method in implementation, not can count on. there 2 possible sourcesiequalitycomparer<t>
implementation used:you can provide explicitly in constructor.
it retrieved automatically
equalitycomparer<t>.default
(by default). if want configure defaultiequalitycomparer<t>
globally accessedequalitycomparer<t>.default
, can use undefault (on github).
Comments
Post a Comment