问题
I recently wrote a couple of structs in .NET, to which I then added implicit conversion operators
Example:
public struct Alpha
{
internal string value;
public static implicit operator Alpha(Beta b)
{
return new Alpha() { value = b.value };
}
public static implicit operator Beta(Alpha a)
{
return new Beta() { value = a.value };
}
}
public struct Beta
{
internal string value;
public static implicit operator Alpha(Beta b)
{
return new Alpha() { value = b.value };
}
public static implicit operator Beta(Alpha a)
{
return new Beta() { value = a.value };
}
}
Test:
Alpha a = default(Alpha);
Beta b = a;
// Ambiguous user defined conversions 'Alpha.implicit operator Beta(Alpha)' and 'Beta.implicit operator Beta(Alpha)' when converting from 'Alpha' to 'Beta'
I would like to know what the rules / best practices are surrounding implicit conversion in C#?
Note to self: My gut feeling is that types should not return objects of another type through implicit conversion? i.e. Beta
should not return Alpha
via implicit conversion, and vice-versa, however, Beta
should return Beta
, and Alpha
should return Alpha
Example (fixed):
public struct Alpha
{
internal string value;
public static implicit operator Alpha(Beta b)
{
return new Alpha() { value = b.value };
}
}
public struct Beta
{
internal string value;
public static implicit operator Beta(Alpha a)
{
return new Beta() { value = a.value };
}
}
Is my assumption correct?
回答1:
You have a Alpha(Beta x)
defined in both classes, thus it is ambiguous which one should be used. Allow each class to handle only the conversion to itself. In other words, struct Alpha
implements Alpha(Beta b)
because it best knows how to create an instance of itself. Also, I would consider implementing explicit conversions instead of implicit. It can sometimes cause bugs or unexpected conversions accidentally, and when dealing with complex classes are often "lossy" conversions.
public struct Alpha
{
internal string value;
public static implicit operator Alpha(Beta b)
{
return new Alpha() { value = b.value };
}
}
public struct Beta
{
internal string value;
public static implicit operator Beta(Alpha a)
{
return new Beta() { value = a.value };
}
}
The only time you'd likely implement "both ways" in a single class, is if the other class has no knowledge of your new class. This is the more common scenario when you want to support conversion to-from a pre-existing class/struct such as supporting conversion to-from a framework type:
public struct Alpha
{
internal string value;
public static implicit operator Alpha(string b)
{
return new Alpha() { value = b };
}
public static implicit operator string(Alpha a)
{
return a.value;
}
}
回答2:
No, your assumpion is not correct (even though you wrote working code thanks to it). The problem in your code is that you have defined the same conversion operators in both classes, this is why they are ambiguous; the compiler cannot decide which one to use.
You can read more in section 6.4.3 (Evaluation of user-defined conversions) of the C# 4.0 Language Specification.
来源:https://stackoverflow.com/questions/25775645/ambiguous-implicit-user-defined-conversions-in-net