使用隐式/显式转换而不是构造函数的原因是什么?

一个例子是:

XNamespace ns = "my namespace" 

为什么不?:

 XNamespace ns = new XNamespace ( "my namespace" ) 

使用隐式/显式转换而不是构造函数背后的想法是什么? 方便?

有这方面的指导方针吗?

方便?

或多或少,是的。 考虑一下你有一个类似数字的对象(例如,一个Complex )你在哪里进行计算的情况。 显然,编写代码如:

 Complex result = c1 * new Complex(2) + new Complex(32); 

非常烦人,难以阅读。 隐式转换在这里有帮助(在本例中,另一种选择是运算符重载,但这会导致大量类似的重载)。

有这方面的指导方针吗?

提供尽可能少的隐式转换,因为它们可能会隐藏问题。 隐式转换将显式性降低了相同的量,从而增加了简洁性。 有时这很好,但有时候不是。

我发现最好将隐式转换限制为非常相似的类型,例如上面示例中类似数字的对象: int本质上是一个Complex (从数学的角度来看;即使它没有通过inheritance建模),因此是隐含的转换是有道理的。

在VB中,隐式转换称为“扩展”(与Narrowing相对,这是explicit ),这很好explicit描述了它:在转换过程中没有信息丢失。

此外,运算符本质上是一个构建器函数,并且具有(某些)构造函数的构建器函数的一些优点:即,它可以重用缓存的值而不是总是创建新的实例。

考虑我的Complex例子。 我们可能想要缓存常用复数的值:

 Class Complex { // Rest of implementation. private static Complex[] cache = new[] { new Complex(-1), new Complex(0), new Complex(1) }; public implicit operator Complex(int value) { if (value >= -1 && value <= 1) return cache[value]; else return new Complex(value); } } 

当然,这种微优化是否有效是另一个问题。

使用XName这样简单类型的隐式转换的原因之一是,我相信,调用方法的便利性。

例如,你可以写

 var info = root.Elements ("user").Element ("info").Value; 

提取数据的简单性就是LINQ的全部内容,如果我们必须写的话

 var info = root.Elements (new XName ("user")).Element (new XName ("info")).Value; 

即使对于最简单的查询,LINQ对于复杂的查询是否完全值得?

这里的另一个重要问题是XNames是雾化的。 请参阅MSDN :

XName对象保证被雾化; 也就是说, 如果两个XName对象具有完全相同的命名空间和完全相同的本地名称,则它们将共享同一个实例 。 为此目的,还明确提供了相等和比较运算符。

除了其他好处之外,此function还允许更快地执行查询。 过滤元素或属性的名称时,谓词中表示的比较使用身份比较,而不是值比较。 确定两个引用实际引用同一个对象比比较两个字符串要快得多。

您无法在构造函数中提供雾化,但定义转换允许您从池中选择相应的对象并将其作为新实例返回。

隐式/显式转换的使用是方便的问题,许多编程指南建议您避免使用显式ConvertToXXX方法。

其中一个问题是隐式/显式转换的使用进一步重载了转换操作符的function。 它赋予它双重目的

  • 通过对象层次结构中的不同类型/接口查看同一对象
  • 将对象完全转换为新类型

不幸的是,C#已经在其他领域(使用原语和拳击)执行后者。

如果两个类应该可以相互转换,但它们不共享自动允许此行为的基类接口,则可以使用转换。 隐式转换永远不应该有数据丢失的可能性; 它们通常被视为“扩大”转换。 例如,将int转换为long是一种扩展转换,并且隐含的转换没有固有的问题。 明确的转换可能涉及数据丢失的可能性; long可能会或可能不会转换为int ,具体取决于其值。

我使用隐式转换的一个技巧是当我没有其他合理的选项时,将不同命名空间中的类转换为彼此。 例如,一个WCF服务返回一个AuthenticationToken对象,我需要将该对象传递给另一个名称空间中的WCF服务。 两者都有这个AuthenticationToken对象,并且常量转换会很痛苦。 我的解决方案涉及在部分类中使用public static implicit operator来添加转换每种方式的function。

就个人而言,当我知道rhs可能被转换为类的静态成员时(比如说color = "red"暗示color = Colors.Red ),我会使用转换

当我打算实际创建一个新实例时,我使用new运算符。