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

╄→尐↘猪︶ㄣ 提交于 2020-01-01 09:33:38

问题


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?


回答1:


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. 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.

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.

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. 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.




回答2:


One of the reasons behind using implicit conversion with such simple types as XName is, I believe, convenience in calling methods.

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

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?

Another important issue here is that XNames are atomized. See MSDN:

XName objects are guaranteed to be atomized; that is, if two XName objects have exactly the same namespace and exactly the same local name, they will share the same 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.




回答3:


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.

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).




回答4:


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. Explicit conversions may involve the possibility of data loss; a long may or may not be convertible to an int, depending on its value.

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. Both have this AuthenticationToken object, and constant conversion would have been a pain. My solution involved using public static implicit operator in a partial class to add the functionality to convert each way.




回答5:


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)

I use the new operator when I intend to actually create a new instance.



来源:https://stackoverflow.com/questions/3815695/whats-the-reason-of-using-implicit-explicit-convertions-instead-of-constructors

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!