views:

769

answers:

3

What are general guidelines on when user-defined implicit conversion could, should, or should not be defined?

I mean things like, for example, "an implicit conversion should never lose information", "an implicit conversion should never throw exceptions", or "an implicit conversion should never instantiate new objects". I am pretty sure the first one is correct, the third one is not (or we could only ever have implicit conversion to structs), and I don't know about the second one.

+1  A: 

I'd agree with the first definitely - the second most of the time ("never say never"), but wouldn't get excited by the third; apart from anything else, it creates an unnecessary distinction between structs and classes. In some cases, having an implicit conversion can vastly simplify a calling convention.

For explicit conversions, all things are possible.

It isn't that often you need to write conversion operators, though. And in many cases, explicit operators are more useful, with the acceptance that they can break if conditions aren't right (for example, with Nullable<T>, if they don't have a value).

Marc Gravell
+8  A: 

The first isn't as simple as you might expect. Here's an example:

using System;

class Test
{
    static void Main()
    {
        long firstLong = long.MaxValue - 2;
        long secondLong = firstLong - 1;

        double firstDouble = firstLong;
        double secondDouble = secondLong;

        // Prints False as expected
        Console.WriteLine(firstLong == secondLong);

        // Prints True!
        Console.WriteLine(firstDouble == secondDouble);        
    }
}

Personally I very rarely create my own implicit conversions. I'm happy enough with the ones in the framework, but I rarely feel that adding my own would make life better. (The same is true of value types in general, btw.)

EDIT: Just to actually answer the question a bit, it's probably worth reading the conversion operators part of the Microsoft class library design guidelines.

Jon Skeet
Ouch! Well, this rather suggests to me that this implicit conversion is a bit broken.
Alexey Romanov
Yes, this link is _exactly_ what I was looking for, thanks!
Alexey Romanov
You do delve into weirdness, don't you?? Where did you come up with this one? :)
Andrew Rollings
@Andrew: well they both have 64 bits and not every double is an integer. Stands to reason there'll be some integers which can't be represented exactly.
Jon Skeet
A: 

The borderline case which caused me to ask this question is a violation of the second one. Namely, I have a Lazy<T> class (doesn't everyone?) and started pondering whether I shouldn't provide an implicit conversion to T. My instinct is to say yes, and the current version does, but I am not too sure.

Alexey Romanov
No, I really wouldn't - as you're potentially doing significant work, it feels wrong to make it implicit. Have an *explicit* conversion, perhaps - but if you're looking for "why is this suddenly executing some code?" an implicit conversion is too easy to miss.
Jon Skeet
After thinking over it a bit more, I am inclined to agree after all.
Alexey Romanov
Or even a method, such as GetValue()
Marc Gravell
Await() in my case, inherited from Future<T>
Alexey Romanov