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

Joa*_*nge 7 .net c# constructor type-conversion base-class-library

一个例子是:

XNamespace ns = "my namespace"
Run Code Online (Sandbox Code Playgroud)

为什么不?:

XNamespace ns = new XNamespace ( "my namespace" )
Run Code Online (Sandbox Code Playgroud)

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

有这方面的指导方针吗?

Kon*_*lph 9

方便?

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

Complex result = c1 * new Complex(2) + new Complex(32);
Run Code Online (Sandbox Code Playgroud)

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

有这方面的指导方针吗?

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

我发现最好将隐式转换限制为非常相似的类型,例如上面示例中类似数字的对象:int基本上是Complex-a(从数学角度来看;即使它没有通过继承建模),因此隐式转换使得感.

在VB中,隐式转换被称为" Widening"(相对于Narrowing,这是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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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


Dan*_*mov 5

我认为,使用XName等简单类型进行隐式转换的原因之一是调用方法的便利性.

例如,你可以写

var info = root.Elements ("user").Element ("info").Value;
Run Code Online (Sandbox Code Playgroud)

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

var info = root.Elements (new XName ("user")).Element (new XName ("info")).Value;
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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