简体   繁体   English

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

[英]What's the reason of using implicit/explicit convertions instead of constructors?

An example would be: 一个例子是:

XNamespace ns = "my namespace"

Why not?: 为什么不?:

XNamespace ns = new XNamespace ( "my namespace" )

What's the idea behind using implicit/explicit convertions instead of constructors? 使用隐式/显式转换而不是构造函数的背后的想法是什么? Convenience? 方便?

Is there a guideline for this? 是否有指导方针?

Convenience? 方便?

More or less, yes. 或多或少,是的。 Consider the case for when you've got a number-like object (say, a Complex ) on which you do calculations. 考虑当您有一个类似数字的对象(例如Complex )进行计算时的情况。 Clearly, writing code such as: 显然,编写如下代码:

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

is very annoying and hard to read. 非常烦人且难以阅读。 Implicit conversions help here (an alternative would be operator overloads in this example, but that would lead to lots of similar overloads). 隐式转换在这里有帮助(在此示例中,一种替代方法是运算符重载,但这会导致很多类似的重载)。

Is there a guideline for this? 是否有指导方针?

Provide as few implicit conversions as possible, since they may hide problems. 提供尽可能少的隐式转换,因为它们可能隐藏问题。 Implicit conversion reduce explicitness by the same amount by which they increase terseness. 隐式转换将显式性降低的程度与其增加简洁性的程度相同。 Sometimes this is good, but sometimes not. 有时候这很好,但有时却不好。

I find it best to restrict implicit conversions to very similar types, such as the number-like objects in my example above: an int essentially is-a Complex (from a mathematical standpoint; even if it's not modelled via inheritance), hence an implicit conversion makes sense. 我发现最好将隐式转换限制为非常相似的类型,例如上面示例中的数字类对象: int本质上是Complex (从数学的角度;即使不是通过继承建模),因此是隐式的转换很有意义。

In VB, an implicit conversion is called “ Widening ” (as opposed to Narrowing , which is explicit ) and this describes it well: no information is lost in the course of the conversion. 在VB中,隐式转换称为“ Widening ”(与Narrowingexplicit )相反),这很好explicit描述了这一点:在转换过程中不会丢失任何信息。

Furthermore, an operator is essentially a builder function, and has (some of) the usual advantages of a builder function over a constructor: namely, it can re-use cached values instead of always creating new instances. 此外,运算符本质上是一个构建器函数,并且具有(某些)构建器函数相对于构造器的通常优点:即,它可以重新使用缓存的值,而不必始终创建新实例。

Consider my Complex example. 考虑我的Complex示例。 We may want to cache values for often-used Complex numbers: 我们可能要缓存常用复数的值:

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

Of course, whether this micro-optimization is effective is another question. 当然,这种微观优化是否有效是另一个问题。

One of the reasons behind using implicit conversion with such simple types as XName is, I believe, convenience in calling methods. 我认为,将隐式转换与XName这样的简单类型一起使用的原因之一是调用方法的方便。

For example, you can write 例如,你可以写

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

Simplicity at extracting data is what LINQ is all about, and if we had to write LINQ的目的是简化数据提取,如果我们不得不写的话

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

even for simplest queries, would LINQ be totally worth it for complex ones? 即使是最简单的查询,LINQ对于复杂的查询也完全值得吗?

Another important issue here is that XNames are atomized. 这里的另一个重要问题是XName被原子化。 See MSDN : 参见MSDN

XName objects are guaranteed to be atomized; 保证XName对象被原子化; that is, if two XName objects have exactly the same namespace and exactly the same local name, they will share the same instance . 也就是说, 如果两个XName对象具有完全相同的名称空间和完全相同的本地名称,则它们将共享相同的instance The equality and comparison operators are also provided explicitly for this purpose. 为此,还明确提供了相等和比较运算符。

Among other benefits, this feature allows for faster execution of queries. 除其他好处外,此功能还可以更快地执行查询。 When filtering on the name of elements or attributes, the comparisons expressed in predicates use identity comparison, not value comparison. 在过滤元素或属性的名称时,谓词中表示的比较使用身份比较,而不是值比较。 It is much faster to determine that two references actually refer to the same object than to compare two strings. 与比较两个字符串相比,确定两个引用实际引用同一对象要快得多。

You can't provide atomization in constructor, but defining a conversion allows you to pick corresponding object from the pool and return it as if it were a new instance. 您不能在构造函数中提供原子化,但是定义转换后,您可以从池中选择相应的对象,并将其作为新实例返回。

The use of implicit / explicit conversions is issue of convenience and one that many programming guidelines suggest you avoid in favor of explicit ConvertToXXX methods. 隐式/显式转换的使用是方便的问题,许多编程准则都建议您避免使用显式ConvertToXXX方法。

One of the problems is tha the use of implicit / explicit conversions further overloads functions of the casting operator. 问题之一是使用隐式/显式转换会进一步重载强制转换运算符的功能。 It gives it the dual purpose of 它具有双重目的

  • Viewing the same object through a different type / interface in the object's hierarchy 通过对象层次结构中的不同类型/接口查看同一对象
  • Coverting the object to a new type altogether 将对象完全覆盖为新类型

Unfortunately C# already does the latter in other areas (with primitives and boxing). 不幸的是,C#已经在其他领域(使用基元和装箱)完成了后者。

If two classes should be convertible to one another, but they do not share an interface of a base class that allows this behavior automatically, you would use the conversions. 如果两个类可以相互转换,但它们不共享自动允许此行为的基类的接口,则可以使用转换。 Implicit conversions should never have a possibility of data loss; 隐式转换永远不会丢失数据; they are often considered "widening" conversions. 它们通常被视为“扩大”转化。 For example, converting an int to a long is a widening conversion, and there is no problem inherent in the conversion being implicit. 例如,将int转换为long就是扩大的转换,并且隐式转换没有内在的问题。 Explicit conversions may involve the possibility of data loss; 显式转换可能会导致数据丢失; a long may or may not be convertible to an int , depending on its value. long可能会转换为int ,也可能无法转换为int ,具体取决于其值。

One trick I have used with implicit conversions is to convert classes in different namespaces to each other when I did not have another reasonable option. 我用于隐式转换的一个技巧是,当我没有其他合理的选择时,将不同名称空间中的类彼此转换。 For example, one WCF service returns an AuthenticationToken object that I need to pass to a WCF service in a different namespace. 例如,一个WCF服务返回一个AuthenticationToken对象,我需要将该对象传递给另一个命名空间中的WCF服务。 Both have this AuthenticationToken object, and constant conversion would have been a pain. 两者都具有这个AuthenticationToken对象,并且进行常量转换将是一件痛苦的事情。 My solution involved using public static implicit operator in a partial class to add the functionality to convert each way. 我的解决方案涉及在部分类中使用public static implicit operator来添加功能以每种方式进行转换。

Personally, I use the conversions when I know that the rhs may be converted into a static member of a class (like saying color = "red" to imply color = Colors.Red ) 就个人而言,当我知道rhs可能会转换为类的静态成员时,我会使用这些转换(例如说color = "red"表示color = Colors.Red

I use the new operator when I intend to actually create a new instance. 我打算实际创建新实例时使用new运算符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 对事件使用对象类型而不是实际类型的原因是什么? - What's the reason of using the Object type instead of an actual type for events? 显式和隐式类型转换有什么区别? - What is the difference between explicit and implicit type casts? 人们使用 get 属性的原因是什么? 放; 而不是字段? - What's the reason for peoples to use properties with get; set; instead of fields? 重写ToString和在C#中使用隐式/显式转换运算符有什么区别? - What is the difference between overriding ToString and using implicit/explicit conversion operators in C#? 使用LINQ的.Cast()运算符时,显式/隐式转换运算符失败 - Explicit/implicit cast operator fails when using LINQ's .Cast() operator 在使用显式等待之前关闭隐式等待,因为显式等待需要隐式等待的时间 - Turning Off Implicit Wait before using explicit wait as explicit wait takes time from Implicit wait 隐式和显式 StringBuilder.ToString() 方法调用之间有什么区别? - What is the difference between implicit and explicit StringBuilder.ToString() method calls? c# 中的显式和隐式接口实现有什么区别 - what is the difference between explicit and implicit interface implementation in c# 隐式和显式转换 - implicit and explicit conversion 字符串和整数,隐式和显式 - Strings and ints, implicit and explicit
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM