質問

So I have a value object, (arbitrarily say money), and I want to implement equality for it. I am aware of the intended/default behavior for == and .Equals() (reference and data equality).

In this case though, I want to be able to compare two objects, and say that they are equivalent for calculations (e.g. 1m and 3 ft are equivalent) however for persistence (using NHibernate, where isDirty I think depends on equality), user display and selection of currency, I want them to be considered different.

Should I, in this case,

  1. Have different behavior for == and .Equals() (and which should do what),
  2. Wherever I want to check equivalency, just check each property (means extra code)
  3. Implement a method like .IsEquivalent() (I'd prefer not to do the latter)
  4. Something else that I'm missing

Is there a best practice/pattern I should follow? Thanks

Edit: i got some responses regarding changing exchange rates. so updating for clarity. lets say height, and not currency

  • I'd like to clarify, some assumptions:
  • // ignore: Value object contains decimal amount, string / class currency
  • // ignore: Exchange rates do not change.
  • // ignore: the class currency is aware of its exhange rate to and from the other
  • value object contains decimal qty, string / class unit
  • the class unit is aware of its conversion to and from the other
  • i do not intend to expand rates / conversions etc

I'm more concerned about practices and patterns, as opposed to implementing currency. Basically, the same approach to a person's height, where height is a value object, ({1,m} to {3,ft}, where 1m is always "equal"/"equivalent" to 3ft)

役に立ちましたか?

解決

I would not treat 1.0 USD as equal to 0.63 GBP. In order to check for equality of monitary value, you'd need more information than just the two values - you'd also need the current exchange rate, etc. This is especially true, as the same two values won't be equal consistently, and equality should always be true if the two values are ever equal.

As such, a method, such as AreEquivalentMonitaryValues(), seems appropriate - especially given that extra info is required.

他のヒント

Since you want different definitions of equality depending on the context you'd want to use an IEqualityComparer.

As Reed suggests equality for the type itself should really mean, "always and forever are equal" rather than equal for the current exchange rates, but having an IEqualityComparer just means that, "from the point of view of this comparer, they are equal". From there you can have your ExchangeRate type, or something that is given an exchange rate, be able to create an IEqualityComparer<Money> object that represents equality for a given exchange rate. That equality comparer can then be used to compare various types of currencies for equality.

Another approach entirely would be to create an "invariant currency", and give your class ToInvariant and FromInvariant methods so that non-invariant currencies are not equal (ever) and invariant currencies can be equal despite the currency that generated the invariant value.

Create a class MoneyExchangeRates which has a method IsWorthApproximatelyTheSame(Money m1, Money m2).

Exchange rates vary over time, don't make them global mutable state.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top