Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 799
Joan Venge Avatar asked Sep 28 '10 18:09

Joan Venge


People also ask

Why is constructor implicit?

Implicit Constructor Chaining This ensures that the creation of the subclass object starts with the initialization of the classes above it in the inheritance chain. There could be any number of classes in an inheritance chain.

Can constructor be called implicitly?

Constructor can only be called implicitly on objects. But destructor can be called implicitly or explicitly. Constructor is always called implicitly whereas Destructor can be called either implicitly or explicitly both ways.

What is an implicit conversion function?

An implicit conversion sequence is the sequence of conversions required to convert an argument in a function call to the type of the corresponding parameter in a function declaration. The compiler tries to determine an implicit conversion sequence for each argument.


2 Answers

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.

like image 185
Konrad Rudolph Avatar answered Oct 17 '22 00:10

Konrad Rudolph


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.

like image 5
Dan Abramov Avatar answered Oct 17 '22 00:10

Dan Abramov