代码之家  ›  专栏  ›  技术社区  ›  Joan Venge

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

  •  7
  • Joan Venge  · 技术社区  · 14 年前

    XNamespace ns = "my namespace"
    

    为什么不呢?:

    XNamespace ns = new XNamespace ( "my namespace" )
    

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

    对此有指导方针吗?

    5 回复  |  直到 14 年前
        1
  •  10
  •   Konrad Rudolph    14 年前

    方便吗?

    或多或少,是的。考虑一下当你有一个类似数字的物体(比如,一个 Complex )你在上面计算。显然,编写代码,例如:

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

    很烦人,很难阅读。隐式转换在这里很有用(本例中的另一种方法是操作符重载,但这会导致许多类似的重载)。

    对此有指导方针吗?

    我发现最好将隐式转换限制为 非常 类似的类型,例如上面示例中的类似数字的对象:一个 int 本质上是-a (从数学的角度看;即使它不是通过继承建模的),因此隐式转换是有意义的。

    Widening (相对于 Narrowing explicit )这很好地描述了它:在转换过程中没有信息丢失。

    此外,操作符本质上是一个构建器函数,它具有构建器函数优于构造函数的一些常见优点:即,它可以重用缓存的值,而不是总是创建新实例。

    想想我的 例子。我们可能希望缓存常用复数的值:

    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);
        }
    }
    

        2
  •  5
  •   Community kfsone    4 年前

    我认为,将隐式转换用于XName这样的简单类型背后的原因之一是调用方法的方便性。

    例如,你可以写

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

    提取数据的简单性是LINQ的核心,如果我们必须编写

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

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

    这里的另一个重要问题是xname是原子化的。 看到了吗 MSDN

    XName对象保证是原子化的;也就是说, 如果两个XName对象具有完全相同的名称空间和完全相同的本地名称,那么它们将共享同一个实例

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

    不能在构造函数中提供原子化,但是 定义转换允许您从池中选取相应的对象,并将其作为新实例返回。

        3
  •  3
  •   JaredPar    14 年前

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

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

    不幸的是,C已经在其他领域(原语和拳击)实现了后者。

        4
  •  2
  •   Andrew    14 年前

    如果两个类应该可以相互转换,但它们不共享允许自动执行此行为的基类接口,则可以使用转换。隐式转换应该 有可能丢失数据;它们通常被认为是“扩大”转换。例如,转换 int long 这是一个不断扩大的转换,而且转换本身没有隐含的问题。显式转换可能涉及数据丢失的可能性;a 长的 内景 ,取决于其值。

    我在隐式转换中使用的一个技巧是,在没有其他合理选项的情况下,将不同名称空间中的类相互转换。例如,一个WCF服务返回一个AuthenticationToken对象,我需要将该对象传递给另一个命名空间中的WCF服务。两者都有这个AuthenticationToken对象,持续转换将是一件痛苦的事情。我的解决方案是使用 public static implicit operator 在一个分部类中添加了各种方式转换的功能。

        5
  •  1
  •   JamesMLV    14 年前

    color = "red" 暗示 color = Colors.Red

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