-
Notifications
You must be signed in to change notification settings - Fork 45
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
Implement operator(s) '<, <=, >, >=' #241
Comments
@CheloXL - thanks for the report. |
The trouble is, not all types that implement
So, Vogen must inspect the primitive type to see if it has these operators. It's acheivable, but just wanted to make a note here for when it's implemented fully |
I see that the duplicate #292 was fixed, but I'm not able to view the changes. Did they not make it into a release? |
@glen-84 - im not sure, I see this issue on mine as well Vogen Version: Note: Here is my // Set the defaults for the project
[assembly:
VogenDefaults(
typeof(Guid),
Conversions.EfCoreValueConverter | Conversions.NewtonsoftJson | Conversions.TypeConverter |
Conversions.SystemTextJson,
typeof(ValueObjectValidationException))] Note: [ValueObject]
// ReSharper disable once PartialTypeWithSinglePart
public readonly partial struct BloomEventCommentId
{
public static bool operator <(
BloomEventCommentId left,
BloomEventCommentId right)
{
return left.CompareTo(right) < 0;
}
public static bool operator <=(
BloomEventCommentId left,
BloomEventCommentId right)
{
return left.CompareTo(right) <= 0;
}
public static bool operator >(
BloomEventCommentId left,
BloomEventCommentId right)
{
return left.CompareTo(right) > 0;
}
public static bool operator >=(
BloomEventCommentId left,
BloomEventCommentId right)
{
return left.CompareTo(right) >= 0;
}
} |
@SteveDunn Any update on this one? I'm not able to apply |
Hi - there's multiple aspects to this:
Now that 1. and 2. are implemented and released, nobody should be seeing any CA errors as far as I know. I hope to get around to this one shortly, but I need to check my notes as I vaguely remember that it was quite a big deal to inspect operators on the underlying type in the source generator |
I've looked back through my notes and found this old issue: (#222) It's non-trivial to inspect the operators on the underlying type, for instance, We could add some hints into the source generator to say 'if the type is int, then always add these operators'. I don't know how that would scale or if that would cause confusion with other types. Another option, but this is a .NET 7+ feature, is to check if the underlying type implements But then we could risk adding more confusion by given the impression that Vogen fully wraps all operators, including:
|
Perhaps a trade off, at least for now, it to have an explicit parameter on the Obviously, this will have to be on each Value Object and can't be defaulted globally (or we'd have all sorts of compilation errors where the underlying types don't themselves have comparison operators). But for sorting, I think what we currently have looks sufficient: the generated I suppose it boils down to what Vogen actually is. I define it as something that more 'strongly types' primitives, e.g.
|
We'd like to be able to use these operators to filter IDs within a certain range, for example. A list of numeric types + the .NET 7-specific |
Another way to make the impact of this smaller is to solve #407 Some people do not need their Value Object to implement |
Does ist make sense to disable the warning for these specifc types (like Guid) and implement the operators for the other types? |
Apologies @szarykott - #407 was merged to main in July but I forgot to do a release. I've just kicked off the release process for 3.0.21. It should be in NuGet in an hour or so. Would be great if you could try it out. |
Since the update, the source generator seems to not work anymore. Thanks! |
Oh no! Sorry about that. I'm not able to fix anything until next week. Perhaps clearing your intermediate files might help. Do you experience this in a new project? |
Oh my bad.. after cleaning up the intermediate files & restarting rider it worked. Is there any restriction for this? My sample id looks like: [ValueObject<int>]
[Instance("Default", 25)]
public readonly partial struct PageSize
{
private static Validation Validate(int input)
{
return input > 0 ? Validation.Ok : Validation.Invalid($"{nameof(PageSize)} must be greater than zero.");
}
public static PageSize FromNullable(int? input) => input.HasValue ? From(input.Value) : Default;
} |
@lk-smit-ag - glad it's now working (you had me worried there!) The operators aren't implemented; the implementation added merely allows types to omit the generation of |
@SteveDunn oh, my fault too! Thanks! |
Forgive me if this is slightly off topic for this issue (#222 would have been a better fit I think, but that's closed)... I'd like to make the case for implementing standard operators for the underlying type in the source generated value object, beyond just the equality and comparison operators. In my use case, I'd like to create value objects for various public static bool operator <(
Foo left,
Foo right)
{
return left.CompareTo(right) < 0;
}
public static bool operator <=(
Foo left,
Foo right)
{
return left.CompareTo(right) <= 0;
}
public static bool operator >(
Foo left,
Foo right)
{
return left.CompareTo(right) > 0;
}
public static bool operator >=(
Foo left,
Foo right)
{
return left.CompareTo(right) >= 0;
}
public static Foo operator +(
Foo left,
Foo right)
{
return From(left.Value + right.Value);
}
public static Foo operator -(
Foo left,
Foo right)
{
return From(left.Value - right.Value);
}
public static Foo operator *(
Foo left,
Foo right)
{
return From(left.Value * right.Value);
}
public static Foo operator /(
Foo left,
Foo right)
{
return From(left.Value / right.Value);
}
// ...and more... The temperature ( I learned from reading this and other issues that there are differences in supported operators based on the underlying type, e.g., The code that is source generated for the operators could be governed by configuration options in the attribute. This could take the form of "simple" grouped options, e.g., none, "match underlying type", etc., or they could be much more fine grained - perhaps an à la carte flags enumeration (with sensible defaults). Clearly those are half-baked thoughts that would require further analysis, but I'm sure there's a solution there. I think without automatically source generated operators, a whole class of use cases for Vogen's value objects are out of reach. It would work well for identifiers and alike, but not for anything that requires math, which I suspect is a common need/use case. At least, not without significant repetitious and error prone manual code, which is what I assume Vogen is partially trying to avoid. I'm new to Vogen, so please be gentle if I've missed something elementary. 😃 The library looks awesome by the way! Thoughts? |
Hi @prlcutting—apologies for the very slow response—this thread is so long that I must've missed it originally. Thanks for the feedback, and I really appreciate that you like the library! The way that I use value objects is to make each operator (
... so I have an But I understand that some value objects are much closer in behaviour to the primitive that they wrap, and your suggestions would certainly help with this and avoid repetitious code. I'll continue to think about how best to implement this. Perhaps it could be achieved by the new static abstracts in interfaces... |
@SteveDunn would it make sense to offer a diagnostic suppressor which would turn off the CA1036 warning on |
Good idea @viceroypenguin . Thanks for the offer. There's a suppressor already that could be used as a reference point https://github.com/SteveDunn/Vogen/blob/main/src/Vogen/Suppressors/CA1822DecoratedMethodSuppressor.cs |
Describe the feature
As the title says, implement the comparison operators. This is to fix the CA1036 warning: AbcId should define operator(s) '<, <=, >, >=' since it implements IComparable.
The text was updated successfully, but these errors were encountered: