-
Notifications
You must be signed in to change notification settings - Fork 164
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Infinite recursion in OneOfBase.GetHashCode() and Equals() #28
Comments
Good find... this is a possible solution, although it involves changing the sig of OneOfBase:
|
How about this: public class OneOfBase<T0, T1, T2> : IOneOf
{
//...
public override int GetHashCode()
{
unchecked
{
int hashCode;
switch (_index)
{
case 0:
hashCode = _value0 is OneOfBase<T0, T1, T2> ? base.GetHashCode() : (_value0?.GetHashCode() ?? 0);
break;
// ...
}
return (hashCode * 397) ^ _index;
}
}
} maybe slightly faster (to be benchmarked): public class OneOfBase<T0, T1, T2> : IOneOf
{
static readonly bool isT0SubclassOfThis = typeof(OneOfBase<T0,T1,T2>).IsAssignableFrom(typeof(T0));
//...
public override int GetHashCode()
{
unchecked
{
int hashCode;
switch (_index)
{
case 0:
hashCode = isT0SubclassOfThis ? base.GetHashCode() : (_value0?.GetHashCode() ?? 0);
break;
// ...
}
return (hashCode * 397) ^ _index;
}
}
} |
I think this can probably be fixed using a similar Will do that if I get some time to work on the library |
Do we have any more insight on this? It's proven to be a significant issue. |
Nope - I haven't got a lot of time to work on it. However, the workaround is pretty simple - don't inherit from the OneOfBase (use a separate base type if you need), and add implicit cast operators to your case Types to get the same syntactical effect as inheriting. |
We've been using OneOfBase happily while overriding all derived |
The latest version of OneOf does OneOfBase slightly differently (so some minor code fixes are needed), but avoids this issue. |
If
OneOfBase
is used with the case classes being subclasses of theOneOfBase
subclass, as in the readme:and
GetHashCode
is not overridden in the case classes,OneOfBase<...>.GetHashCode
will just call itself, resulting in a stack overflow. (If it is overriden, it works, but the base impl becomes pointless.). Same problem withEquals
.Not sure offhand what would be the best solution, especially without breaking the use case where the case types are not subclasses of the
OneOfBase
, and are possibly value types. And without making things harder for users who don't care about equality comparison (e.g. by adding a type constraint likeIEquatableCaseClass
).The text was updated successfully, but these errors were encountered: