如何允许隐式转换?

15

假如有以下代码:

class Json
{
}

class Program
{
    static void Main(string[] args)
    {
    }

    Json MyAction()
    {
        return "{\"json\": 1}";
    }
}

有什么东西我可以添加到Json类中,使其编译通过吗?有什么方法可以让编译器知道它可以将字符串隐式转换为Json吗?


1
我会添加一个.ToJson()扩展方法,而不是重载implicit操作符,因为这种隐式转换违反了一些重要的指南(请参见Saeed的答案)。特别是它可能会抛出异常,在比较中语义奇怪并且不是无损的。 - CodesInChaos
@CodeInChaos:我可以让它不抛出异常 :) 我最大的担忧是,该操作返回一个不同的类型以区分它与字符串,尽管在其他方面它可以像字符串一样完美地工作。这样,我就知道要设置哪个ContentType,而无需用户进行任何额外的工作(只需适当设置函数的返回类型)。 - mpen
3个回答

45

C#中的implicit操作符声明允许你指定:

{type to convert to} ({type to convert from} variablename)

这是一个简单的例子:

class Json
{
    private Json(string json)
    {
        //logic to parse string into object
    }

    public static implicit operator Json(string input)
    {
        return new Json(input);
    }
}

一些笔记:

  • 首先,我不会必然采用这种方法,因为您应用程序中的大多数字符串与JSON字符串在语义上并不等效。转换运算符的目的是说两种类型始终表示语义上等效的信息(或足够接近以便有用地被视为这样)。我建议在您的Json类上实现static Json Parse(string input)甚至可能是static bool TryParse(string input, out Json json)方法。通常,调用方应该知道它是否期望自己的字符串包含Json。

  • 通常,如果我的类从类型提供隐式类型转换,我发现最好使任何解析或ctor逻辑针对相同类型private。这确保了消费者只有一种方法来执行特定的操作,而不是两种方法(ctor和conversion)- 因此在上面的示例中使用了私有构造函数。这可能会有例外,但对我来说这是一个很好的一般规则。

  • 隐式转换还允许某些有趣的比较运算符。例如,现在您可以从字符串隐式转换为json,您还可以执行以下操作:if(myJson == "blah"),它将进行转换,然后在您的Json对象上调用 == 运算符,默认情况下会执行引用相等性比较。


答案中的“implicit”链接已经过时。请查看:用户定义的转换运算符 - Flimtix

4

添加一个隐式操作符:

public static implicit operator Json(string s)
{
   return new Json(s);
}

implicit关键字用于声明一个隐式的用户定义类型转换运算符。使用它来在用户定义类型和另一种类型之间启用隐式转换,如果该转换保证不会导致数据丢失。


3
您可以使用隐式转换器,但要注意不要丢失数据:
通过消除不必要的强制转换,隐式转换可以提高源代码的可读性。然而,由于隐式转换可以在程序员未指定的情况下发生,因此必须小心以防止出现不愉快的意外。一般来说,隐式转换运算符不应抛出异常,也不应丢失信息,以便在程序员没有意识到的情况下安全地使用。如果转换运算符无法满足这些标准,则应将其标记为显式。
请参见 MSDN

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接