CSharpFunctionalExtensions icon indicating copy to clipboard operation
CSharpFunctionalExtensions copied to clipboard

`EnumValueObject` - Allow for `int` and implementation example?

Open jeffward01 opened this issue 1 year ago • 2 comments

I've been searching for a bit, and am wondering if you had a moment to post that blog post. The only documentation I can find on this class (other than the code) is:

  • https://github.com/vkhorikov/CSharpFunctionalExtensions/issues/274
  • https://github.com/vkhorikov/CSharpFunctionalExtensions/issues/314

Thanks!

My implementation of EnumValueObject I would like to use it to represent 'votes'.

For example, let's look at the votes on Reddit

Yourself as a user can perform these voting actions on a post:

  • Do nothing (Neutral)
  • Vote it up, (Upvote)
  • Vote it down (DownVote)

I have an application in which I have 'comments', and I would like to add this feature.

I would like the ValueObjectEnum values to be something like:

  • Dowvote: -1
  • Neutral: 0
  • Upvote: 1

It could even be:

  • Neutral: 0
  • Downvote: 1
  • Upvote: 2

The numbers are an int and represent an index. I saw in the code that it only allows for string.

Is there any way I can use an int instead of a string?

If not, would you be open to a PR which brought the feature over from SmartEnum

Or possibly even the best solution, allow for a dependency (or optional dependency in a separate NuGet package of SmartEnum

Originally posted by @jeffward01 in https://github.com/vkhorikov/CSharpFunctionalExtensions/issues/255#issuecomment-1367084399

jeffward01 avatar Dec 29 '22 05:12 jeffward01

It seems that the int is already possible.

Here is my implementation:

// As regular class, see sealed implementation below
public class VoteDirection : EnumValueObject<VoteDirection, int>
{
    public static readonly VoteDirection Neutral = new VoteDirection(1, nameof(Neutral));
    public static readonly VoteDirection DownVote = new VoteDirection(2, nameof(DownVote));
    public static readonly VoteDirection UpVote = new VoteDirection(3, nameof(UpVote));
    
    /// <inheritdoc />
    protected VoteDirection(int id,
        string name)
        : base(id, name)
    {
    }
}

Just posting this here so that when devs search for 'Issues', this result will be available.

1.) How is my implementation?

2.) Should my parent class of VoteDirection beor sealed? -- which is preferred? would there be any side-effects with sealed regarding the private constructor?

3.) Would it be possible to use -1 as an index? * I think not, and even if you could, it might introduce side-effects elsewhere in your code.

Implementation as sealed:

public sealed class VoteDirection : EnumValueObject<VoteDirection, int>
{
    public static readonly VoteDirection Neutral = new VoteDirection(1, nameof(Neutral));
    public static readonly VoteDirection DownVote = new VoteDirection(2, nameof(DownVote));
    public static readonly VoteDirection UpVote = new VoteDirection(3, nameof(UpVote));

    /// <inheritdoc />
    private VoteDirection(
        int id,
        string name)
        : base(id, name)
    {
    }
}

Edit:

I was just thinking that this would also be a very cool Error type object @xavierjohn (I know your working on an error collection extension, so just wanted to mention you incase you found this helpful)

jeffward01 avatar Dec 29 '22 05:12 jeffward01

I don't understand the relationship between the enum and the error.

From a domain perspective, the values are 'Neutral', 'DownVote' & 'UpVote', so what role does values 1,2 & 3 have? If it is to save on storage, the translation will be in the DTO.

xavierjohn avatar Dec 30 '22 00:12 xavierjohn