We are using implicit conversion operators in several models, e.g. in KeyId
/// <summary>
/// An implicit conversion operator for this type from string.
/// </summary>
public static implicit operator KeyId(string value) {
if (!TryParse(value, out var keyId)) {
throw new FormatException($"The specified value ({value ?? "[null]"}) is not a valid string representation of a {nameof(KeyId)}.");
}
return keyId;
}
/// <summary>
/// An implicit conversion operator for this type to string.
/// </summary>
public static implicit operator string(KeyId id) {
return id.ToString();
}
This is generally considered a bad idea: You effectively lose type-safety when passing models as method arguments. For example, the following call will not cause a compile-time error:
public void DoSomething(KeyId id, ShortGuid guid) {}
service.DoSomething("", "");
In this example, both string values are implicitly converted to KeyId and ShortGuid. But because of the two way conversion, the following works too:
public void DoSomething(KeyId id, ShortGuid guid) {}
KeyId id = new KeyId("one");
ShortGuid guid = ShortGuid.NewGuid();
service.DoSomething(guid, id); // Wrong order!
This compiles, because both arguments are first implicitly converted to string and then back to the type of the argument.
And that, my friends, is very confusing. This should not be possible.
There is a relatively easy fix, however: Just make one of the conversion operators explicit. But that is a breaking change for consumers.
We are using implicit conversion operators in several models, e.g. in
KeyId
This is generally considered a bad idea: You effectively lose type-safety when passing models as method arguments. For example, the following call will not cause a compile-time error:
In this example, both string values are implicitly converted to
KeyId
andShortGuid
. But because of the two way conversion, the following works too:This compiles, because both arguments are first implicitly converted to
string
and then back to the type of the argument.And that, my friends, is very confusing. This should not be possible.
There is a relatively easy fix, however: Just make one of the conversion operators explicit. But that is a breaking change for consumers.