Implmement `IFormattable` for `[ValueObject<string>]`
Describe the bug
It looks like Vogen implements IFormattable by default if the underlying type does; which makes sense.
But this is also useful in cases where you have a [ValueObject<string>] — which is obviously "formattable", even if string, the primitive type, technically doesn't implement IFormattable.
I would argue this should even be done by default, or there should at least be an opt-in option to instruct Vogen to implement IFormattable for [ValueObject<string>]s as well, enabling the developer to choose.
Steps to reproduce
This
using Vogen;
Console.WriteLine("Hello, World!");
[ValueObject<string>]
public readonly partial struct Vo;
... generates this:
public readonly partial struct Vo : global::System.IEquatable<Vo>, global::System.IEquatable<System.String>, global::System.IComparable<Vo>, global::System.IComparable, global::System.IParsable<Vo>
{
// omitted for brevity
Expected behaviour
IFormattable should be implemented, either by default, or via an option. Currently, neither is possible.
Oops! Thanks for reporting @aradalvand - I'll take a look at soon as time permits
Hi @aradalvand - I was just taking a look at this. What purpose does the ToString overload have when the underlying is already a string? ToString on the value object just delegates to the ToString on the primitive. The format parameter has no meaning on string, so it's just the format provider.
Vogen already implements this for string:
public global::System.String ToString(global::System.IFormatProvider? provider) => IsInitialized() ? Value.ToString(provider) ?? "" : "[UNINITIALIZED]";
This is useful when you want to abstract over types that implement IFormattable — imagine, for instance, a T that is constrained to IFormattable because it needs to be printed onto some human-readable medium (e.g. terminal). In that case, Vogen types that have an underlying type of string can't be specified as T even though it does make sense for them to be able to.
I might be missing something so let me know what you think.
@aradalvand - in the situation described, String cannot be passed
Print("Hello world");
static void Print<T>(T t) where T : IFormattable => Console.WriteLine(t.ToString("G", CultureInfo.InvariantCulture));
The type 'string' must be convertible to 'System.IFormattable' in order to use it as parameter 'T' in the generic local function 'void Print<T>(T)
I don't know if I'm missing something (it's usually the case! 😆 )