隐式转换运算符和相等运算符

时间:2012-03-23 09:58:55

标签: c# operator-overloading implicit-conversion implicit-cast

假设我有一个支持隐式转换为System.String

的简单对象
public sealed class CompanyCode
{
    public CompanyCode(String value)
    {
        // Regex validation on value format
        _value = value;
    }

    private readonly String _value;

    public override String ToString()
    {
        return _value;
    }

    static public implicit operator String(CompanyCode code)
    {
        if(code == null)
            return null;

        return code.ToString();
    }
}

现在让我们说我的程序的另一部分我用字符串进行比较:

var companyCode = { some company code object }

if (companyCode == "MSFTUKCAMBS")
    // do something...

编译器使用==运算符做了什么?它是否隐式地将companyCode转换为字符串并运行System.String ==实现?它是否使用System.Object ==实现?或者编译器会抱怨我? (我现在没有编译器来检查这个。)

据我所知,我还有其他两种选择。

  • 在CompanyCode上实施==(String x)运算符。
  • 在CompanyCode上实施IEquatable<String>界面。

这些选项中的任何一个(或两个)是否更可取?

3 个答案:

答案 0 :(得分:5)

  

假设我有一个支持隐式转换为System.String

的简单对象

我会质疑这个设计决定。事实上,它提出了运算符重载的问题,这表明你的同事会问同样的问题。我甚至不知道答案(就编译器将要做的事情而言)。

我绝对不会建议实施IEquatable<string>,因为x.Equals(y)不会与y.Equals(x)对称。你可能在你的班级中实现==的两个重载,两种方式都是圆的...但是它与Equals不一致。

我建议只有一个名为ValueCode类型字符串的属性,然后你可以使用:

if (companyCode.Value == "MSFTUKCAMBS")

将立即明确这意味着什么。

基本上,我认为隐含转换适当的情况非常少而且很远。

来自Design Guidelines for Class Library Developers

  

如果最终用户没有明确期望这种转​​换,请不要提供转化运营商。

这里有这么明确的期望吗?

答案 1 :(得分:2)

我个人建议不要在这些情况中使用operator overloading。查看代码,了解发生了什么,这有点令人困惑。

这是一个更好的,imo,有一些明确显示比较操作的功能,或者像Jon建议的那样,使用一个属性。

简而言之,为您的代码读者清楚地了解您要比较的内容。

答案 2 :(得分:2)

它将隐式转换为字符串并使用字符串的==运算符检查相等性。 对于你展示的情况 - 你提供的每种方式都是合适的,但每种方式都有不同的目的和意义。

通常应避免隐式转换。 实现==是为了与字符串进行比较, IEquatable只是允许使用类作为IEquatable类型,用于外部代码引用。 IEquatable可能只返回==结果。

对于这种情况,我会选择==运算符重载,除非你有任何其他目的使用隐式转换。

另外,如果你使用隐式转换,它会在代码方面更加丑陋但是更加健壮,可以重载EXPLICIT转换,而不是隐式转换,所以每当想要将类转换为字符串时,他将不得不使用(字符串)obj来强制转换它,这也是对代码中真正发生的事情的一个很好的提醒。